如何终止Fetch请求

到目前为止,在浏览器里用 JavaScript 发起请求的方式有两种:XMLHttpRequest 和 fetch。XMLHttpRequest 我们比较熟悉,存在很长时间了,而 fetch 是 ES6 才引入的。

XMLHttpRequest 是可以中途取消的,如下所示:

let xhr = new XMLHttpRequest();

xhr.method = 'GET';

xhr.url = 'https://slowmo.glitch.me/5000';

xhr.open(method, url, true);

xhr.send();

// 随后取消这个请求

abortButton.addEventListener('click', function() {

 xhr.abort();

});

fetch 刚开始引入的时候并不支持终止操作。最早的关于终止 fetch 请求的 GitHub issue  是在 2015 年提出的。在 fetch 规范之外,有不少解决这个问题的尝试,比如 cancelable-promises 和其他 hacks 手段。

但是现在我们终于有了通用的AbortController 和 AbortSignal API。这些 API 是由 DOM 标准而不是语言本身提供的。

AbortController 是何方神圣

AbortController

DOM 规范文档 是这样描述的:

虽然  promise 没有内置的中断机制,很多使用它的 API 需要这个中止语义。AbortController就是通过提供abort() 方法切换相应 AbortSignal 对象的状态,从而满足这种需求的。想要支持终止功能的 API 可以接受一个AbortSignal 对象,然后根据它的状态决定如何继续。

// 创建 AbortController 实例

const controller = new AbortController();

const signal = controller.signal;

// 监听 abort 信号, controller.abort() 执行时触发回调

signal.addEventListener('abort', () => {

 console.log(signal.aborted); // true

});

// 稍后调用终止方法,发出信号

controller.abort();

如何通过 AbortController 终止 fetch 请求?

fetch 接受 AbortSignal作为第二个参数的一部分。

const controller = new AbortController();

const signal = controller.signal;

//  5s 后请求收到响应,注意第二个参数

fetch('https://slowmo.glitch.me/5000', { 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);

   }

 });

// 2秒后取消请求

setTimeout(() => {

 controller.abort();

}, 2000);

终止  fetch  会同时终止请求和响应,并抛出new DOMException('Aborted', 'AbortError')错误。另外,同一个 AbortSignal对象(上例中的signal)可以用于取消多个fetch请求。

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):