axios之CancelToken取消请求

v0.22.0 开始,Axios 支持以 fetch API 方式------ AbortController 取消请求

此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用

官网链接

1. 背景

最近项目中遇到一个场景,当连续触发一个请求时,如果是同一个接口,则保留最后一次的请求,之前的请求取消。

查阅了下axios文档,有一个属性CancelToken,把这个添加到axios配置中

2. 使用

1:在request时,添加cancelToken

javascript 复制代码
  request: [
    (config: AxiosRequestConfig) => {
      const cacheKey = `${config.method}${config.url}`
     
      if (config.autoCancel) {
        removeCache(cacheKey)
      }
      config.cancelToken = new axios.CancelToken((c) => {
        caches[cacheKey] = c
      })
      return config
    },
    (error: any) => Promise.reject(error),
  ],

2:在reponse时,删除key

javascript 复制代码
  response: [
    (res: AxiosResponse) => {
      const cacheKey = `${res.config.method}${res.config.url}`
      if (res.config.autoCancel) {
        removeCache(cacheKey)
      }
      return res
    },
    (error: any) => Promise.reject(error),
  ],

3:判断是否存在重复请求

javascript 复制代码
const caches: Record<string, Canceler> = {}
function removeCache(key: string) {
  if (caches[key]) {
    
    caches[key]()
    delete caches[key]
  }
}

这里的autoCancel 是为了解决url相同,请求参数不同时,自定义添加的,具体请求方式可以根据这个值来决定是否开启cancelToken

3. 全部代码

javascript 复制代码
/**
 * 通过取消重复请求解决请求"竞态"问题
 * - 如何定义"重复":method和url相同
 */
import axios, { AxiosRequestConfig, Canceler, AxiosResponse } from 'axios'

const caches: Record<string, Canceler> = {}
function removeCache(key: string) {
  if (caches[key]) {
    caches[key]()
    delete caches[key]
  }
}

const cancelInterceptors = {
  request: [
    (config: AxiosRequestConfig) => {
      const cacheKey = `${config.method}${config.url}`
      if (config.autoCancel) {
        removeCache(cacheKey)
      }
      config.cancelToken = new axios.CancelToken((c) => {
        caches[cacheKey] = c
      })
      return config
    },
    (error: any) => Promise.reject(error),
  ],
  response: [
    (res: AxiosResponse) => {
      const cacheKey = `${res.config.method}${res.config.url}`
      if (res.config.autoCancel) {
        removeCache(cacheKey)
      }
      return res
    },
    (error: any) => Promise.reject(error),
  ],
}

export default cancelInterceptors

在封装的axios里面添加配置

javascript 复制代码
// 往request请求中添加配置
service.interceptors.request.use(...cancelInterceptors.request)

// 往response请求中添加配置
service.interceptors.response.use(...cancelInterceptors.response)

在response失败error中axios返回了一个失败状态axios.isCancel(error)

javascript 复制代码
(error: AxiosError) => {
    // if (axios.isCancel(error) && error.message === SCRM_CANCEL_MESSAGE) {
    //   // 被手动取消的数据统计接口,不展示提示
    if (axios.isCancel(error)) {
      // 被取消的接口,不展示提示
    } else {
      message.error(error.response?.statusText || error.message || '网络错误')
    }

    // 网络层面错误,如接口地址写错了会走到这里
    return Promise.reject(error)
  }

3. 原理

source file:axios/lib/adapters/xhr.js

1:创建请求

javascript 复制代码
var request = new XMLHttpRequest()

if (config.cancelToken) {
  // Handle cancellation
  config.cancelToken.promise.then(function onCanceled(cancel) {
    if (!request) {
      return;
    }

    request.abort();
    reject(cancel);
    // Clean up request
    request = null;
  });
}

2:创建新的取消

在source file:axios/lib/cancel/CancelToken.js

javascript 复制代码
  var token = this;
  executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
}

2:取消请求

在axios/lib/adapters/xhr.js文件中取消**request.abort();**请求,

javascript 复制代码
if (config.cancelToken) {

  // Handle cancellation

  config.cancelToken.promise.then(function onCanceled(cancel) {

    if (!request) {

      return;

    }



    request.abort();

    reject(cancel);

    // Clean up request

    request = null;

  });

}

笔记

相关推荐
ly768939 分钟前
JavaScript 从入门到进阶:核心语法、异步编程与工程化实践
开发语言·javascript·ecmascript
why技术1 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
excel1 小时前
记录升级 nuxt3 到 nuxt4 记录
前端
剑胆琴心静水深流2 小时前
全栈之路6---web集成与呈现
前端·vue.js·spring boot·分布式·spring·前端框架·npm
前端snow2 小时前
ai agent -- Memory汇总
前端
ITresearchGuest2 小时前
AI 焦虑下,前端该何去何从
前端·人工智能
沙盘客2 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享
Codiggerworld3 小时前
Chrome DevTools 隐藏神技:这 5 个调试技巧你可能从来没用过
前端·chrome·chrome devtools
旋生万物3 小时前
【终极实战】用Python从零“生成“一个宇宙:螺旋干涉模型的代码实现
开发语言·前端·人工智能·react.js·php·wpf
IT_陈寒3 小时前
被Java的final坑惨了,这些细节你可能也忽略了
前端·人工智能·后端