axios 是否可以取消请求

133 阅读3分钟

axios请求可以取消的。

1. 请求取消的原理

axios 的请求取消功能依赖于 CancelToken。CancelToken 是一个用于取消请求的令牌,它可以通过 CancelToken.source() 方法创建。每个 CancelToken 实例都有一个 token 和一个 cancel 方法。当调用 cancel 方法时,与该 token 关联的请求将被取消。

1)创建 CancelToken 实例

使用 CancelToken.source() 工厂方法生成一个包含 token 和 cancel 的对象:

const source = axios.CancelToken.source(); 
// source = { token: CancelToken实例, cancel: 取消请求的函数 }

2)令牌与请求的绑定

发起请求时,将 source.token 传递到请求配置的 cancelToken 字段:

axios.get('/api/data', {
  cancelToken: source.token
});

axios 内部会监听该 token 的状态变化。

3)触发取消操作

调用 source.cancel(reason) 时,token 的状态被标记为“已取消”,并传递取消原因(reason)。 Axios 检测到 token 状态变化后,立即中止与该 token 关联的请求,并抛出 Cancel 错误。

取消请求的流程

(1)用户触发某个操作,发起一个请求。 

(2)在请求完成之前,用户触发了另一个操作,需要取消之前的请求。 

(3)调用 cancel 方法,Axios 中断之前的请求。 

(4)发起新的请求。

2.代码结构

1)创建axios实例

const instance: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
  },
});

baseURL: 从环境变量中获取 API 的基础 URL。 

timeout: 设置请求超时时间为 5 秒。 

headers: 设置默认请求头为 application/json。

2)取消令牌的管理

const cancelTokenMap = new Map<string, CancelTokenSource>();

cancelTokenMap: 使用 Map 数据结构来存储每个请求的取消令牌。键是请求的 URL,值是对应的 CancelTokenSource。

作用: 通过 URL 快速查找和取消对应的请求。

3)请求拦截器

instance.interceptors.request.use(
  (config) => {
    // 添加 token 到请求头
    const token = localStorage.getItem('token');
    if (token) {
      config.headers = config.headers || {};
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

功能: 在请求发送前,检查本地存储中是否存在 token,如果存在则将其添加到请求头中。

作用: 实现全局的请求头管理,例如身份验证。

4)响应拦截器

instance.interceptors.response.use(
  (response: AxiosResponse) => {
    // 清理已完成的请求记录
    const url = response.config.url;
    if (url && cancelTokenMap.has(url)) {
      cancelTokenMap.delete(url);
    }

    // 处理全局响应逻辑
    if (response.data.code !== 0) {
      return Promise.reject(response.data);
    }
    return response.data;
  },
  (error) => {
    // 清理失败的请求记录
    const url = error.config?.url;
    if (url && cancelTokenMap.has(url)) {
      cancelTokenMap.delete(url);
    }

    // 处理全局错误
    if (error.response?.status === 401) {
      // 处理未授权
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

功能: 

    在请求成功时,清理 cancelTokenMap 中对应的请求记录。

    在请求失败时,清理 cancelTokenMap 中对应的请求记录,并根据状态码处理全局错误

作用: 实现全局的响应和错误处理逻辑。

3.请求取消的实现原理

 1)CancelToken 的作用

CancelToken.source(): 创建一个 CancelTokenSource 对象,包含 token 和 cancel 方法。 token: 用于关联请求。

 cancel: 用于取消请求。

2)请求取消的流程

发起请求时,创建一个 CancelTokenSource,并将其存储到 cancelTokenMap 中。

 如果需要取消请求,调用 cancelRequest 或 cancelAllRequests 方法。 

调用 cancel 方法后,Axios 会中断与该 token 关联的请求,并抛出一个 Cancel 错误。 

在响应拦截器中,清理已完成的请求记录。