Javascript 异步编程得益于 Promise 的实现,它们极大地提高了Web开发的性能和体验。不过原生的 Promise 有个最大的缺点就是一旦请求发出去,我们就无法取消它。但是我们找到了另一种方法来实现。
DOM 标准中添加了一个称为 AbortController 的新的控制器,该控制器允许我们将其用作取消HTTP fetch 请求的信号。它利用 AbortSignal 属性来执行此操作。
它是在2017年添加的,并且在大多数浏览器中都支持(显然,除了IE)。但是既然已经抛弃对IE的支持,因此这真的是一件大事。
为什么我们需要取消 HTTP 请求?
在我们讨论如何去取消之前,我们先了解下为什么需要取消 HTTP fetch 请求。当我们的应用程序是由可以动态添加到 DOM 树和从 DOM 树删除的多个组件组成的时候,许多组件都必须独立进行相应的HTTP请求。可能发生的情况是,在获取请求完成之前,将其中一个组件卸载。这种情况多发生在网速慢的情况下,或者在页面正在跳转时用户离开了该页面。
由于请求是异步的,因此它将在后台继续执行。并且如果处理不当,可能会导致一些错误。
谷歌浏览器的fetch请求默认超时时间是300秒,火狐浏览器是90秒。这些还都是在网络正常的情况下。因此,如果需要的话,我们绝对希望通过自己的方式来终止HTTP的fetch请求。
AbortController和AbortSignal
AbortController和AbortSignal API是由DOM标准提供,这样即使Web标准变化了它仍然可以继续使用。我们来声明一个控制器:
const controller = new AbortController();
和一个signal常量
const signal = controller.signal;
这个控制器仅仅只有一个abort方法。并且该方法一旦被触发,立即通知signal
-
controller.abort();
-
signal.addEventListener(
'abort',
() => {
-
console.log(signal.aborted);
// true
-
});
如何取消一个HTTP fetch请求
fetch Api本身不允许以编程方式取消请求。但是它可以将AbortSignal作为参数。这样一来,如果我们一旦需要,我们就可以在特定的时间段内中止这个请求。
-
const controller =
new AbortController();
-
const signal = controller.signal;
-
-
-
-
-
fetch(url, { signal })
-
.catch(
err => {
-
if (err.name ===
'AbortError') {
-
console.log(
'Fetch was aborted');
-
}
-
});
-
// Abort the request after 4s
-
// aborts the fetch with 'AbortError'
-
setTimeout(
() => {
-
controller.abort();
-
},
4000);
我们甚至可以自己封装一个带有延迟参数的fetch请求的函数
-
async
function cancellableFetch(url, data, timeout = 4000) {
-
const controller =
new AbortController();
-
const timer =
setTimeout(
() => controller.abort(), timeout);
-
-
-
const response =
await fetch(url, {
-
...data,
-
signal: controller.signal
-
});
-
clearTimeout(timer);
-
return response;
-
}
值得注意的是:
如果我们将同一个signal传递给多个请求,如果一旦终止就取消了所有的请求。所以,它只能在如果一个请求失败将取消所有请求的情况下使用。
由于控制器不能多次使用,如果我们不想在取消一个HTTP fetch请求时终止所有的请求,那么就需要为所有的控制器创建一个新的实例。
请求的取消仅发生在客户端。尽管客户端收不到响应,服务器仍可能会对其进行处理。
我们也可以使用Promise.race来实现此功能,但是该解决方案会使请求挂起而不是中止请求。它将继续在后台消耗带宽。
以上就是在耗时终止HTTP fetch 请求的方法,不知道有没有疑问,欢迎留言!
转载:https://blog.csdn.net/u013919171/article/details/113520557