如何在客户端终止一个已经发出的HTTP请求

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 请求的方法,不知道有没有疑问,欢迎留言!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值