写点什么

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

作者:南城FE
  • 2022 年 7 月 08 日
  • 本文字数:1763 字

    阅读完需:约 6 分钟

在日常前端开发中, 经常会遇到频繁发起的重复请求, 会给服务器及网络造成不必要的压力, 可通过取消重复请求解决

场景

  • 订单数据条件筛选查询

  • 表单提交按钮频繁点击

  • 路由页面切换请求未取消

解决方案

在每个请求发起的时候存储当前存储的标记在一个数组或 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 requestcancel();
复制代码

项目中封装使用

基本变量定义


// 是否取消重复请求开关const cancelDuplicated = true
// 存储每个请求中的mapconst 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()})
复制代码

总结

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

参考

axios官网取消请求


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

用户头像

南城FE

关注

还未添加个人签名 2019.02.12 加入

专注前端开发,分享前端知识

评论

发布
暂无评论
Vue路由切换&Axios接口取消重复请求_Vue_南城FE_InfoQ写作社区