从第一个实现 Fetch API 的浏览器开始计算,现在已经是第 7 个年头了。现在各大浏览器对 Fetch API 的支持已经相当不错了。ES6 的不断普及,我们基本上在编码上都会使用 Promise 和 Async/Await,异步编程的今天,可能已经忘记了如何去编写一个 XMLHttpRequest。Fetch API 的易用性让不少小伙伴转入了它的怀抱。
简单的 Fetch 请求
fetch('https://bar.com/foo', {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ foo: 'bar' }),
}).then(console.log);
这是一个简单的 Fetch 请求, 只要传入一个配置项,就能创建出一个简单直观的 fetch 请求。 而且相对于 XMLHttpRequest 来说,提供了更多的控制参数,例如 credentials 和 redirect 等。可以让使用者去配置是否携带 cookies 或者是跳转等。而且 Fetch API 天然的异步,避免了回调地狱。很符合今天异步编程的大环境。
所以我们可以通过 Async/Await 去简化我们的代码。
const res = await fetch('https://bar.com/foo', {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ foo: 'bar' }),
});
console.log(res);
如果现在使用 XMLHttpRequest,我们需要调用 open() 方法开启一个请求, 然后调用其他的方法或者设置参数来定义请求,最后调用 send() 方法发起请求,再在 onload 或者 onreadystatechange 事件里处理数据。
一套组合拳下来,只能说 Fetch API 真香。
进阶功能
从上文来看,Fetch API 相对比与 XMLHttpRequest 具有不少的优势,但是 XMLHttpRequest 给我们提供了 3 个简单的方法来进行取消请求、超时取消、下载进度功能。我们只需要简单的配置就可以是心啊这三个功能。但是 Fetch API 却没有提供这 3 个功能,我们只能手动实现这 3 个功能。
中断请求
在 XMLHttpRequest 中, 我们调用一个 abort() 方法,就可以中断请求,XMLHttpRequest 还有 onabort 事件,可以监听请求的中断并做出响应。
在 Fetch API 中,我们只能使用 AbortController 与 AbortSignal 来进行请求的中断
const abortController = new AbortController();
fetch('https://bar.com/foo', {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ foo: 'bar' }),
signal: abortController.signal, // 连接 abortController
}).then(console.log);
abortController.abort(); // 取消请求
abortController.signal.onAbort = console.log; // 监听取消事件
通过 AbortSignal 来连接 AbortController 与 fetch 实例,AbortSignal 中的 onAbort 事件会在请求中断之后触发。
超时中断
既然我们已经实现了中断请求,我们只需要使用 setTimeout 就可以模拟一个超时时间,实现超时中断.
const abortController = new AbortController();
fetch('https://bar.com/foo', {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ foo: 'bar' }),
signal: abortController.signal, // 连接 abortController
}).then(console.log);
setTimeout(() => abortController.abort(), 10 * 1000); // 10s 后取消请求
abortController.signal.onAbort = console.log; // 监听取消事件
获取下载进度
在所有配置项中,我们都不能看到有关于下载进度的配置。那我们应该如何去实现这个功能呢?
在下一节中,会介绍和它相关的 Streams API,了解了之后,我们再来揭晓如果获取 fetch 下载进度。