详细参考链接:
Fetch API 教程 - 阮一峰的网络日志Fetch API - Request对象 - 《阮一峰 Web API 教程》 - 书栈网 · BookStack
更详细的一个中文文档
Request属性:credentials_w3cschool
Postman 有个代码查看器,可以很方便地看http请求在fetch中的拼装模式,同时还能对比XMLHttpRequest与两者的区别
浏览器控制台network中也有这个功能
原始Promise写法:
fetch(url)
.then(response => response.json()) // 如果response是json的化,否则调用response.text()
.then(console.log) // 这里才能输出response.body的值
.catch(console.log) // 这里输出异常
async fetchFunc(){ // 同步写法
const response = await fetch(url)
const text = await reponse.text();
console.log(text)
}
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = "json";
xhr.onload = function(){
console.log(xhr.response)
}
xhr.onerror = function(){
console.log("出错了")
}
xhr.send()
数据流读取器:
.text() // 返回字符串
.json() // 返回json对象
.formData() // 返回FormData 对象
.blob() // 返回blob对象
.arrayBuffer() // 返回二进制数组ArrayBuffer对象
fetch()
fetch方法的第一个参数可以是 URL 字符串,也可以是后文要讲到的Request对象实例。Fetch方法返回一个Promise对象,并将一个response对象传给回调函数。
response对象有一个ok属性,如果返回的状态码在200到299之间(即请求成功),这个属性为true,否则为false。因此,判断请求是否成功的代码可以写成下面这样。
fetch('./api/some.json').then(function (response) {
if (response.ok) {
response.json().then(function (data) {
console.log(data);
});
} else {
console.log('请求失败,状态码为', response.status);
}
}, function(err) {
console.log('出错:', err);
});
response对象除了json方法,还包含了服务器 HTTP 回应的元数据。
fetch('users.json').then(function(response) { console.log(response.headers.get('Content-Type')); console.log(response.headers.get('Date')); console.log(response.status); console.log(response.statusText); console.log(response.type); console.log(response.url);});
上面代码中,response对象有很多属性,其中的response.type属性比较特别,表示HTTP回应的类型,它有以下三个值。
-
basic:正常的同域请求
-
cors:CORS 机制下的跨域请求
-
opaque:非 CORS 机制下的跨域请求,这时无法读取返回的数据,也无法判断是否请求成功
如果需要在 CORS 机制下发出跨域请求,需要指明状态。
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(function(response) {
return response.text();
})
.then(function(text) {
console.log('Request successful', text);
})
.catch(function(error) {
log('Request failed', error)
});
除了指定模式,fetch 方法的第二个参数还可以用来配置其他值,比如指定 cookie 连同 HTTP 请求一起发出。
fetch(url, { credentials: 'include'})
发出 POST 请求的写法如下。
fetch('http://www.example.org/submit.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'firstName=Nikhil&favColor=blue&password=easytoguess'
}).then(function(res) {
if (res.ok) {
console.log('Perfect! Your settings are saved.');
} else if (res.status == 401) {
console.log('Oops! You are not authorized.');
}
}, function(e) {
console.log('Error submitting form!');
});
body属性:
Request对象和Response对象都有body属性,表示请求的内容。body属性可能是以下的数据类型。
-
ArrayBuffer
headers.append("x-log-compresstype", "lz4")
var input = Buffer.from(reqPayload);
var maxOutputSize = lz4.encodeBound(reqPayload.length);
var output = Buffer.alloc(maxOutputSize);
var compressedSize = lz4.encodeBlock(input, output);
output = output.slice(0, compressedSize);
fetch(url, {
method: "POST",
headers,
body: output
}).then(response => console.log(response))
-
ArrayBufferView (Uint8Array等)
-
Blob/File 总结的规律是可以把发出去的内容都视为普通的内容,并不需要做额外处理
var reqPayload = JSON.stringify({
__logs__: arr
});
let headers = new Headers({
"x-log-apiversion": "0.6.0",
"x-log-bodyrawsize": reqPayload.length
})
let blob = new Blob([reqPayload], {
type: "application/x-protobuf"
});
headers.append('Content-Type', "application/x-protobuf")
fetch(url, {
method: "POST",
headers,
body: blob
}).then(response => console.log(response))
-
string
-
URLSearchParams
var u = new URLSearchParams();
u.append('method', 'flickr.interestingness.getList');
u.append('api_key', '<insert api key here>');
u.append('format', 'json');
u.append('nojsoncallback', '1');
var apiCall = fetch('https://api.flickr.com/services/rest?' + u);
-
FormData
var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
method: "POST",
body: form
})
Request Data 总结
fetch 发什么出去不重要,fetch底层会根据你传入的body类型在底层都是以 2 进制传输过去,关键点在于后端怎么解析这个二进制文件,后端是根据 Content-Type 来正确解析这些二进制的,所以关键还在于 Content-Type 设置成什么样子,发送逻辑都是将对应类型的值复制给 Body
Fetch 的 Cookie 概念
在开发过程中,因为涉及的是插件开发,在 Background 中调用 Fetch,此时是没有域名的,而之前无论用 Ajax 发送请求的时候,也不能直接自己指定 Cookie 传到服务端,这里应该区分对待前端 http.request 和后端 request 请求,前端因为受到平台浏览器的约束,对某些功能是不放开的,尤其是调用浏览器本身自带的对象,是有底层约束的,所以不能自定义敏感 Cookie 这种事情,自然是解决不了的,这也是之前的知识判断失误。