JavaScript 的 promise 一直是该语言的一大胜利——它们引发了异步编程的革命,极大地改善了 Web 性能。原生 promise 的一个缺点是,到目前为止,还没有可以取消 fetch 的真正方法。 JavaScript 规范中添加了新的 AbortController ,允许开发人员使用信号中止一个或多个 fetch 调用。 以下是取消 fetch 调用的工作流程:
以下是取消 Fetch 请求的基本步骤:
1const controller = new AbortController();
2const { signal } = controller;
3
4fetch("http://localhost:8000", { signal })
5 .then((response) => {
6 console.log(`Request 1 is complete!`);
7 })
8 .catch((e) => {
9 console.warn(`Fetch 1 error: ${e.message}`);
10 });
11
12// Abort request
13controller.abort();在 abort 调用时发生 AbortError ,因此你可以通过比较错误名称来侦听 catch 中的中止操作。
1catch(e => {
2 if(e.name === "AbortError") {
3 // We know it's been canceled!
4 }
5});将相同的信号传递给多个 fetch 调用将会取消该信号的所有请求:
1const controller = new AbortController();
2const { signal } = controller;
3
4fetch("http://localhost:8000", { signal })
5 .then((response) => {
6 console.log(`Request 1 is complete!`);
7 })
8 .catch((e) => {
9 console.warn(`Fetch 1 error: ${e.message}`);
10 });
11
12fetch("http://localhost:8000", { signal })
13 .then((response) => {
14 console.log(`Request 2 is complete!`);
15 })
16 .catch((e) => {
17 console.warn(`Fetch 2 error: ${e.message}`);
18 });
19
20// Wait 2 seconds to abort both requests
21setTimeout(() => controller.abort(), 2000);杰克·阿奇博尔德(Jack Archibald)在他的文章 Abortable fetch 中,详细介绍了一个很好的应用,它能够用于创建可中止的 Fetch,而无需所有样板
1function abortableFetch(request, opts) {
2 const controller = new AbortController();
3 const signal = controller.signal;
4
5 return {
6 abort: () => controller.abort(),
7 ready: fetch(request, { ...opts, signal }),
8 };
9}说实话,我对取消 Fetch 的方法并不感到兴奋。在理想的世界中,通过 Fetch 返回的 Promise 中的 .cancel() 会很酷,但是也会带来一些问题。无论如何,我为能够取消 Fetch 调用而感到高兴,你也应该如此!