开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
Fetch API简介
Fetch是在window对象上实现的接口,用于发起网络请求,和Ajax性质相同,但在设计上比Ajax更友好,主要体现在:
- fetch将不同性质的接口放到了不同的对象中,而Ajax所有东西都放在了一起
- fetch返回Promise对象,解决了Ajax通过回调容易形成回调地狱的窘境
fetch函数
/*
* @param input 接收一个url字符串或者 Request 对象
* @param options 请求配置Object,可以参照 Request 对象的options
* @param return Promise 成功时resolve
*/
function fetch(input, [options]) {
return Promise
}
发送请求
// fetch默认GET请求,一般传参通过url?传递
fetch('/bff/home').then((res) => {
return res.text() // 响应结果转为文本,得到一个 Promise
}).then((text) => {
console.log(text, 'text')
})
发送POST请求,传递json数据
// 发送POST请求
fetch('/test/auth/login', {
method: 'POST',
body: JSON.stringify({ // body传参,只能是字符串
user_id: 123
}),
headers: new Headers({ // 设置body格式为json
'Content-Type': 'application/json'
})
}).then((res) => {
return res.json() // 响应结果转为json对象,得到一个 Promise
}).then((json) => {
console.log(json, 'json')
})
response方法转换响应数据格式
Response对象可以单独实例化,但使用fetch请求完成后得到的就是一个 Response 对象,一般极少会出现自己实例化 Response 的情况
response对象可以通过内置方法来得到响应内容的格式,每一个方法返回的都是一个Promise
fetch('/test/auth/login').then((res) => {
return res.json() // 得到一个json格式的Promise,最常用,如果接口返回的格式无法转化为json则会报错
return res.text() // 得到一个text格式的Promise,以文本的形式得到响应数据
return res.arrayBuffer() // 得到一个buffer格式的Promise
return res.blob() // 得到一个blob格式的Promise
return res.formData() // 得到一个formData格式的Promise
}).then(data => {
console.log('想要的数据格式', data)
})
单独构建请求对象
请求体可以单独构建一个对象,这方便重复发起请求用
var myRequest = new Request('/test/auth/login', {
method: 'POST',
body: JSON.stringify({
user_id: 123
}),
headers: new Headers({
'Content-Type': 'application/json'
})
});
fetch(myRequest).then((res) => {
return res.json()
}).then((json) => {
console.log(json, 'json')
})
Request 对象
new Request(url, options);
- url表示请求资源的路径,无特殊情况一般为字符串
- options 是请求的相关配置
const options = {
method: 'GET', // 请求方式
headers: new Headers({
'Content-Type': 'application/json'
}), // 请求头,一般为 Headers 实例化对象,或者Object
body: JSON.stringify({
user_id: 123
}), // 请求的body,格式可以为:[Blob, BufferSource, formData, URLSearchParams, USVString, ReadableStream]
mode: 'cors', // 请求方式,默认为cors,允许跨域请求;可选值参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Request/mode
credentials: 'omit', // 请求中cookie的处理,默认值为:omit:不发送cookie;可选值为 same-origin:同源时发送,include: 总是发送
cache: 'default', // 请求的缓存方式,参考https://developer.mozilla.org/zh-CN/docs/Web/API/Request/cache
redirect: 'follow',
referrer: 'client',
integrity: ''
}
Headers 构造函数
在Request中,设置请求头可以使用一个对象,或者构建一个 Headers 对象,后者的好处主要是Headers类中提供了一些方法给我们:
var myHeaders = new Headers({
'Content-Type': 'application/json'
});
// 添加一行新的请求头,如果key重名,检查是否接受多个值,如果接受则添加到value后面
myHeaders.append('Access-Token', token);
// 移除一行请求头
myHeaders.delete('Access-Token');
// 得到headers的可迭代对象
var list = myHeaders.entries()
for (var pair of list) {
console.log(pair[0]+ ': '+ pair[1]);
}
// 获取headers的某一项
myHeaders.get('Access-Token');
// 判断headers是否具有某一项
myHeaders.has('Access-Token');
// 得到headers的key可迭代对象
myHeaders.keys();
// 得到headers的values可迭代对象
myHeaders.keys();
// 设置headers的某一项,如果不存在则添加,如果存在则整个覆盖
myHeaders.set('Access-Token');
取消请求
fetch请求可以通过 AbortController 对象进行中止,但需要注意的是 AbortController 兼容性并不是特别好。
// 构建一个 AbortController对象,并获取该对象的标志
const controller = new AbortController();
let signal = controller.signal;
// 把标志传递给fetch配置,如果取消了fetch会进入reject
fetch('/list', { signal }).then(function(response) {
//...
}).catch(function(e) {
reports.textContent = 'Download error: ' + e.message;
})
// 通过 AbortController对象取消请求
controller.abort()
和axios相比
axios是一套成熟的请求库,在原生ajax的基础上做了功能的完善和拓展,而fetch只是基础的api,能和ajax相比,但axios作为插件库,和fetch严格上并不属于同一级别,axios兼容性和功能性都不是fetch可比的。
- axios可以在node服务端使用,而fetch是挂载到window对象上的,只支持浏览器中使用
- axios封装了请求前和请求后的拦截钩子,fetch原生并没有这种实现
- axios有独立的不同的请求函数,如get、post等,fetch全靠配置
- ...
总之,fetch和axios并不是一种类别的东西,也许有一天,会有一款基于fetch的请求库比axios更优秀,也许有一天axios会采用fetch实现。
什么时候应该使用
- 简单的演示项目,不含复杂请求的demo
- 技术生态中有基于fetch封装的插件,如vueuse/useFetch
- ...