原文链接:Aborting a fetch request,by GANAPATI V S
在现在的浏览器中,有两种主要的方法发送请求:XMLHttpRequest
和 fetch
。XMLHttpRequest
这个接口在浏览器中存在很长一段时间了,fetch
则是 ES2015 引入的特性。
XMLHttpRequest
可以在请求中途终止(abortable)。举个例子:
let xhr = new XMLHttpRequest();
xhr.method = 'GET';
xhr.url = 'https://slowmo.glitch.me/5000';
xhr.open(method, url, true);
xhr.send();
// Abort the request at a later stage
abortButton.addEventListener('click', function() {
xhr.abort();
});
复制代码
fetch 刚开始引入时并不支持终止请求。Github 上最早 在 2015 年就有终止 fetch
请求的提案 issue 出现。在 fetch 规范之外也有许多解决这个问题的方案,像 cancelable-promises 和其他 hacks。
终于,通用的 AbortController
和 AbortSignal
API 出来了。该 API 在 DOM 标准 中定义,而不是在语言规范中定义的。
什么是 AbortController
?
DevTools 中输出的 AbortController
函数
DOM 文档 中有这么一段话:
虽然 Promise 没有提供内置的终止算法(aborting mechanism),但是许多使用它们的 API 需要终止语义。
AbortController
提供一个abort()
方法来支持这些需求,这个方法用来切换相应AbortSignal
对象的状态。希望支持终止功能的 API 可以接受AbortSignal
对象,并基于其状态来确定执行流程。
// 创建一个 AbortController 实例
const controller = new AbortController();
const signal = controller.signal;
// 监听 abort signal(终止信号),调用 controller.abort() 后,会触发这里的回调
signal.addEventListener('abort', () => {
console.log(signal.aborted); // true
});
// 稍后执行终止操作,这会通知给 signal 知道
controller.abort();
复制代码
如何使用 AbortController
终止 fetch
请求?
fetch
方法的第二个参数支持配置一个 signal
选项,其值就是 AbortSignal
对象。
const controller = new AbortController();
const signal = controller.signal;
// API 3s 后返回响应
// 注意,这里第二个参数用了一个 'signal' 选项
fetch('https://slowmo.glitch.me/3000', { signal })
.then(r => r.json())
.then(response => console.log(response))
.catch(err => {
if (err.name === 'AbortError') {
console.log('Fetch was aborted');
} else {
console.error('Oops!', err);
}
});
// 2s 后执行终止操作
// 这会导致 fetch 请求被终止,同时产生一个 'AbortError' 错误。
setTimeout(() => {
controller.abort();
}, 2000);
复制代码
这种终止方式,包括终止 fetch 的请求和相应。请求失败时,出现错误 new DOMException('Aborted', 'AbortError')
。
另外,同一个
AbortSignal
(即上面使用的signal
)对象可以用于多个fetch
请求。
demo
点击这里的链接查看线上 demo:codesandbox.io/s/abortable…
demo 截图
AbortController
不是说只能给fetch
使用。它是用来终止异步任务的通用 API。例如,你可以用它来 实现一个可被取消的 Promise。
浏览器兼容性和 polyfill
很多旧浏览器还不支持 AbortController
和 AbortSignal
API。下面有可供你使用的 polyfills。
感谢阅读,希望这篇文章能对你有所帮助!
引用
致谢
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。
(完)