Vue路由切换&Axios接口取消重复请求

Posted 南城FE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue路由切换&Axios接口取消重复请求相关的知识,希望对你有一定的参考价值。

场景

  • 订单数据条件筛选查询
  • 表单提交按钮频繁点击
  • 路由页面切换请求未取消

解决方案

在每个请求发起的时候存储当前存储的标记在一个数组或Map中, 针对每个请求的时候在请求拦截中查询是否重复, 如果已重复则取消历史中重复的请求, 再发起当前请求, 如果没有重复, 则添加存储标记并正常请求, 已请求完成的清除存储标记

axios中如何取消请求

  1. 可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get(/user/12345, 
  cancelToken: source.token
).catch(function(thrown) 
  if (axios.isCancel(thrown)) 
    console.log(Request canceled, thrown.message);
   else 
     // 处理错误
  
);

axios.post(/user/12345, 
  name: new name
, 
  cancelToken: source.token
)

// 取消请求(message 参数是可选的)
source.cancel(Operation canceled by the user.);
  1. 还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token:
const CancelToken = axios.CancelToken;
let cancel;

axios.get(/user/12345, 
  cancelToken: new CancelToken(function executor(c) 
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  )
);

// cancel the request
cancel();

项目中封装使用

基本变量定义

// 是否取消重复请求开关
const cancelDuplicated = true

// 存储每个请求中的map
const pendingXHRMap = new Map()

// 取消请求类型定义 便于后期对此类型不做异常处理
const REQUEST_TYPE = 
  DUPLICATED_REQUEST: duplicatedRequest

设置重复标记的函数

const duplicatedKeyFn = (config) => 
  // 可在此设置用户自定义其他唯一标识 默认按请求方式 + 请求地址
  return `$config.method$config.url`

添加到请求记录

const addPendingXHR = (config) => 
  if (!cancelDuplicated) 
    return
  
  const duplicatedKey = JSON.stringify(
    duplicatedKey: duplicatedKeyFn(config),
    type: REQUEST_TYPE.DUPLICATED_REQUEST
  )
  config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => 
    if (duplicatedKey && !pendingXHRMap.has(duplicatedKey)) 
      pendingXHRMap.set(duplicatedKey, cancel)
    
  )

删除请求记录

const removePendingXHR = (config) => 
  if (!cancelDuplicated) 
    return
  
  const duplicatedKey = JSON.stringify(
    duplicatedKey: duplicatedKeyFn(config),
    type: REQUEST_TYPE.DUPLICATED_REQUEST
  )
  if (duplicatedKey && pendingXHRMap.has(duplicatedKey)) 
    const cancel = pendingXHRMap.get(duplicatedKey)
    cancel(duplicatedKey)
    pendingXHRMap.delete(duplicatedKey)
  

axios中使用

// 请求拦截处理
axios.interceptors.request.use(config => 
    removePendingXHR(config)
    addPendingXHR(config)
    ...
    return config
)

// 响应拦截处理
axios.interceptors.response.use(response => 
    removePendingXHR(response.config)
    ...
, error => 
    // 如果是取消请求类型则忽略异常处理
    let isDuplicatedType;
    try 
      const errorType = (JSON.parse(error.message) || ).type
      isDuplicatedType = errorType === REQUEST_TYPE.DUPLICATED_REQUEST;
     catch (error) 
      isDuplicatedType = false
    
    if (!isDuplicatedType) 
        // 其他异常处理
    
)

Vue中当路由切换页面的时候,将上一个页面的所有请求取消

router.beforeEach((to, from, next) => 
    // 遍历pendingMap,将上一个页面的所有请求cancel掉
    pendingXHRMap.forEach((cancel) => 
        cancel();
    );
    pendingXHRMap.clear()
)

总结

本文主要介绍了在日常前端开发中, 遇到各种情况下频繁发起的重复请求, 会给服务器及网络造成不必要的压力, 可通过取消重复请求解决。

参考

如何优雅的解决”重复请求“问题

以上是关于Vue路由切换&Axios接口取消重复请求的主要内容,如果未能解决你的问题,请参考以下文章

vue axios拦截器常用之重复请求取消

vue axios拦截器常用之重复请求取消

Vue+Axios:使用拦截器来取消多次重复的请求

Vue2学习小记-给Vue2路由导航钩子和axios拦截器做个封装

vue防止接口重复请求实现方法

取消路由更改请求 (React/Redux/Axios)