控制并发请求,取消多余的请求

AbortControllerAxiosCancelToken 都是用于取消请求的机制,但它们有一些重要的区别,尤其是在使用场景和实现方式上。以下是对这两者的详细比较:

1. AbortController

简介

AbortController 是一种原生的浏览器 API,它允许你通过 AbortController 对象控制一个或多个 Fetch 请求和其他支持该信号的操作。

使用示例
const controller = new AbortController();
const signal = controller.signal;

fetch('/some-url', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Request was aborted');
    } else {
      console.error('Fetch error:', error);
    }
  });

// 取消请求
controller.abort();
优点
  • 标准化AbortController 是现代浏览器的标准 API,并且与 Fetch API 紧密集成。
  • 多用途:不仅可用于取消网络请求,还可以取消其他异步操作,只要这些操作支持信号参数。
  • 广泛支持:越来越多的浏览器和框架开始支持 AbortController
缺点
  • 相对较新:在某些旧版浏览器中可能不支持,需要使用 polyfill。
  • 不兼容性:需要确保你的 HTTP 库(如 Axios)可以兼容 AbortController

2. AxiosCancelToken

简介

CancelToken 是 Axios 提供的一种取消请求的机制,它允许你通过 CancelToken 对象取消特定的 Axios 请求。

使用示例
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/some-url', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
})
.then(response => {
  console.log(response.data);
})
.catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    console.error('Axios error:', thrown);
  }
});

// 取消请求
cancel('Operation canceled by the user.');
优点
  • 内置功能:直接集成到 Axios 中,无需额外配置。
  • 简单易用:API 设计简单,易于理解和使用。
缺点
  • 局限性:只能用于取消 Axios 的请求,不能用于其他异步操作。
  • 废弃通知:Axios 团队宣布将在未来的版本中废弃 CancelToken,建议用户转向使用 AbortController

总结

AbortController
  • 适用范围:广泛,除了网络请求,还可以用于其他支持信号的异步操作。
  • 标准化:现代浏览器的标准 API。
  • 兼容性:需要确保所有相关库都支持 AbortController
CancelToken
  • 适用范围:专用于 Axios 请求取消。
  • 简单易用:直接集成到 Axios 中,但将来会被废弃。

推荐使用 AbortController

鉴于 CancelToken 将在未来版本中被废弃,推荐使用 AbortController 进行请求取消。以下是如何在 Axios 中使用 AbortController

import axios from 'axios';

const controller = new AbortController();

axios.get('/some-url', {
  signal: controller.signal
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  if (error.name === 'AbortError') {
    console.log('Request was aborted');
  } else {
    console.error('Axios error:', error);
  }
});

// 取消请求
controller.abort();

更新你的 AxiosCanceler 实现

以下是使用 AbortController 更新你的 AxiosCanceler 实现的示例:

import { AxiosRequestConfig } from 'axios';

// 用于存储每个请求的标识和取消函数
const pendingMap = new Map<string, AbortController>();

const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&');

export class AxiosCanceler {
  // 添加请求(只请求第一次)
  public addPending(config: AxiosRequestConfig): void {
    const url = getPendingUrl(config);
    if (!pendingMap.has(url)) {
      // 如果当前请求不在等待中,将其添加到等待中
      const controller = new AbortController();
      config.signal = config.signal || controller.signal;
      pendingMap.set(url, controller);
    }
    // 如果存在相同URL的请求,则什么都不做
  }

  // 移除请求
  public removePending(config: AxiosRequestConfig) {
    const url = getPendingUrl(config);
    if (pendingMap.has(url)) {
      // 如果当前请求在等待中,取消它并将其从等待中移除
      const abortController = pendingMap.get(url);
      if (abortController) {
        abortController.abort();
      }
      pendingMap.delete(url);
    }
  }

  // 清空所有请求
  public removeAllPending() {
    pendingMap.forEach((controller) => {
      controller.abort();
    });
    pendingMap.clear();
  }
}

这种方法使用了现代浏览器的标准 API,具有更大的灵活性和广泛的适用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值