如何终止 Fetch 请求

作者: 1024译站 | 来源:发表于2020-03-09 15:53 被阅读0次

到目前为止,在浏览器里用 JavaScript 发起请求的方式有两种:XMLHttpRequestfetchXMLHttpRequest 我们比较熟悉,存在很长时间了,而 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 手段

但是现在我们终于有了通用的AbortControllerAbortSignal 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请求。

Fetch 请求被取消

更多前端技术干货尽在微信公众号:1024译站


微信公众号:1024译站

相关文章

网友评论

    本文标题:如何终止 Fetch 请求

    本文链接:https://www.haomeiwen.com/subject/khreqhtx.html