Axios利用拦截器取消页面切换pending中的请求

我们在开发时 经常会遇到类似场景

  • 切换页面时,某些情况导致 当前页面pending中的请求未完成,切换到新页面,之前的请求逻辑还会异常处理

今天,我们解决类似问题:

处理流程:

当前页面 请求拦截 新页面 当前请求cancel函数与url 存储到内存(vuex)数组中 利用router.beforeEach 取消pending请求,清空数组 当前页面 请求拦截 新页面

代码:

vuex定义模块cancel.js

  • cancelTokenArr {arr} 用来存储当前请求数据
  • addCancelToken {function} 添加请求
  • clearCancelToken {function} 取消请求并且清空数组
export default {
    state: {
        cancelTokenArr:[] // 存储cancel token
    },
    mutations: {
        addCancelToken({cancelTokenArr},data){
            cancelTokenArr.push(data)
        },
        clearCancelToken(state){
            state.cancelTokenArr.map(item => {
                item.cancel(`${item.url}---路由切换取消请求`)
            })
            state.cancelTokenArr = []
        }
    }
}

request.js

请求发出前,利用拦截器将取消的cancel函数与当次url利用addCancelToken存储到内存(vuex)中

import axios from 'axios'
import store from '../store'

// 请求拦截器
axios.interceptors.request.use(config => {
   // 请求发出时,添加到cancelTokenArr中
   config.cancelToken = new axios.CancelToken(e => {
       store.commit('addCancelToken', {
           cancel: e,
           url: location.host + config.url
       })
    })
  })
  return config
}, error => {
  Message.error('未知错误')
  return Promise.reject(error)
})

请求发出后,利用响应拦截器处理取消请求

axios.interceptors.response.use(response => {...},error => {
  // 这里判断异常情况,如果axios.isCancel 为 true时,说明请求被取消
  if (axios.isCancel(error)) {
    // 请求取消
    console.warn(error)
    console.table([error.message.split('---')[0]], 'cancel')
  } else {...}
}

利用router.beforeEach切换路由时取消当前pending中的请求

main.js 或者 router.js

// 切换路由时取消正在pending的请求
router.beforeEach((to, from, next) => {
   store.commit('clearCancelToken')
   next()   
}

总结:

  • vuex存储数据
    存储当前的请求函数与url,支持新增清除
  • 请求拦截器
    利用vuex数组存储每次发出请求取消函数以及url
  • 路由切换前
    取消pending中的请求并且清除当前存储的请求数组

效果:
在这里插入图片描述至此,我们就成功拦截页面切换时pending中的请求

链接:

### 使用 Axios 拦截并防止重复请求 为了拦截并阻止重复请求,在创建 Axios 实例时可以设置自定义的拦截逻辑。通过维护一个活动请求集合来跟踪正在进行中的请求,当新请求到来时先检查该集合是否存在相同的请求。如果存在,则取消新的请求;反之则将其加入到集合中。 ```javascript const pendingRequests = new Map(); // 添加唯一标识符作为key用于存储pending状态下的请求 function generateRequestId(config) { return [config.method, config.url, JSON.stringify(config.params), JSON.stringify(config.data)].join('&'); } axios.interceptors.request.use((config) => { const requestId = generateRequestId(config); if (pendingRequests.has(requestId)) { // 存在相同请求,返回Promise.reject表示拒绝此次请求 return Promise.reject(new Error('Duplicate request detected')); } else { // 将当前请求存入Map对象 pendingRequests.set(requestId, true); // 请求成功发送后清除记录 config.__cancelToken__ = axios.CancelToken.source(); config.cancelToken = config.__cancelToken__.token; return config; } }, error => Promise.reject(error)); axios.interceptors.response.use(response => { const requestId = generateRequestId(response.config); // 清理已完成的请求 pendingRequests.delete(requestId); return response; }, error => { const { config } = error; if (config && !error.response) { // 取消请求的情况处理 if (!axios.isCancel(error)) { const requestId = generateRequestId(config); // 若请求取消也应清理对应的标记 pendingRequests.delete(requestId); } } return Promise.reject(error); }); ``` 此代码片段展示了如何利用 `axios` 的请求和响应拦截器功能[^1] 来实现对重复提交请求的有效控制,并且提供了相应的错误处理机制以确保程序健壮性。每当有新的 HTTP 请求发出之前都会经过这个过滤过程,从而避免不必要的资源浪费以及可能引发的数据一致性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端小小白zyw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值