axios中CancelToken的应用

27 阅读2分钟

重复请求

  1.  import axios from 'axios';
      // 创建一个 CancelToken 对象
     const source = axios.CancelToken.source();
      // 发送请求
     axios.get('/api/data', {
       // 将 cancelToken 属性设置为上面创建的 CancelToken 实例
       cancelToken: source.token
     }).then(response => {
       console.log(response.data);
     }).catch(error => {
     // 如果请求被取消则进入该方法判断
         if (axios.isCancel(error)) {
             console.log("已取消的重复请求:" + error.message);
           } else {
             // 添加异常处理
           }
       console.error(error);
     });
      // 取消之前的请求
     source.cancel('Duplicate request');
    
  2.  const CancelToken = axios.CancelToken;
     let cancel;
     ​
     axios.get('/user/12345', {
       // 在options中直接创建一个cancelToken对象
       cancelToken: new CancelToken(function executor(c) {
         cancel = c;
       })
     });
     ​
     // 取消上面的请求
     cancel();
     ​
     ​
    

创建了一个请求队列 pending ,然后为请求配置添加了一个 cancelToken ,并将其推入请求队列中。在发送新的请求之前,我们遍历请求队列,将之前的所有请求都取消掉,并从请求队列中移除。同时,我们还需要在响应拦截器中将已经完成的请求从请求队列中移除。

 import axios from 'axios';
  // 创建一个请求队列
 let pending = [];
 const CancelToken = axios.CancelToken;
 const removePending = (config) => {
   for (let p in pending) {
     if (pending[p].url === config.url + '&' + config.method) {
       pending[p].cancel("request canceled");
       pending.splice(p, 1);
     }
   }
 }
  // 添加请求拦截器
 axios.interceptors.request.use(
   (config) => {
     removePending(config);
     config.cancelToken = new CancelToken((c) => {
       pending.push({ cancel: c, url: config.url + '&' + config.method });
     });
     return config;
   },
   (error) => {
     return Promise.reject(error);
   }
 );
  // 响应拦截器
 axios.interceptors.response.use(
   (response) => {
     removePending(response.config);
     return response;
   },
   (error) => {    removePending(response.config);
         if (axios.isCancel(error)) {
         console.log("已取消的重复请求:" + error.message);
       } else {
         // 添加异常处理
       }
     return Promise.reject(error);
   }
 );

上个请求过慢覆盖下个请求

其实也是重复请求,只不过这里采用的是外部实例去操作cancel,可操作性更强,兼容性更好,颗粒度更小

 //index.service
 import { onMounted, reactive, ref, toRefs, watch, nextTick } from 'vue';
 import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
 const request = axios.create({
   baseURL: '/',
   headers: {
     'Content-Type': 'application/json;charset=utf-8',
   }
 });
 const CancelToken = axios.CancelToken;
 export const getPermissionByManageIdApi = () => {
   const cancelTokenObj: any = reactive({ cancel: null }); //vue双向绑定
   const url = `/auth-pend/api/auth_manager/gain_auth_data_by_manageid`;
   const getPermissionByManageIdRequst = params => {
     return request.get(url, {
       params,
       cancelToken: new CancelToken(function executor(c) {
         cancelTokenObj.cancel = c;
         console.log(cancelTokenObj.cancel);
       })
     });
   };
   return {
     cancelTokenObj,
     getPermissionByManageIdRequst
   };
 };

引用

 import {
 getPermissionByManageIdRequst
 } from './index.service';
 ​
 const { cancelTokenObj, getPermissionByManageIdRequst } =getPermissionByManageIdApi();
 const getPermissionByManageId = async (
   all,
   clientType,
   managerId,
   position
 ) => {
   cancelTokenObj?.cancel && cancelTokenObj.cancel();
   await getPermissionByManageIdRequst({
     all,
     clientType,
     managerId
   })
     .then(({ data }) => {})
     .catch(() => {});
 };