Axios在vue中切換route時取消所有請求

2023 - 04 -07 更新

在v0.22.0版本後官方棄用了CancelToken的方法,並改支援AbortController
在使用AbortController一定要記得檢查自己的版本號
換成AbortController整體概念與CancelToken相同

window._axiosPromiseArr = [] // 全局聲明 (變數掛在window下)
    // http request 拦截器
axios.interceptors.request.use(
    config => {
        config.headers = {
            'Content-Type': 'application/json;charset=UTF-8'
        };
       // 每个请求都会 加入 
       const controller = new AbortController()
        config.signal = controller.signal
        window._axiosPromiseArr.push(controller)
        return config
},

路由跳前

router.beforeEach((to, from, next) => {
  window._axiosPromiseArr.forEach((el, index) => {
    el.abort() // 路由跳转之前,中止请求
    //  重置 window._axiosPromiseArr
    delete window._axiosPromiseArr[index]
  })
  next();
})

目前還有遇到過一個需求是如果有重複呼叫api行為時,取消上一個呼叫
主要的問題是如何判斷此api為同一個api
整體的思路是使用Symbol() (存在requestId)來為api創建id, 呼叫api前利用這個id推到new Map當中,
如果回傳成功以後再從new Map裡使用id找到對應的function將其刪除
目前有方法但是待優化,因為變成每個需要判斷的api都要新增一個Symbol()…

 const requestIdMap = new Map()
  service.interceptors.request.use(
    function (config) {
      /*--以上省略--*/
      if (!config.requestId) return config

      let controller = requestIdMap.get(config.requestId)
      if (controller) {
        controller.abort()
        requestIdMap.delete(config.requestId)
      }

      controller = new AbortController()

      requestIdMap.set(config.requestId, controller)
      config.signal = controller.signal
      return config
    },
    function (error) {
      return Promise.reject(error)
    }
  )
  // 響應攔截器
  service.interceptors.response.use(
    function (response) {
      if (response.config.signal) requestIdMap.delete(response.config.signal)
      return response.data
    },
    async function errorHandler(error) {
      if (error.message !== 'canceled') {
        requestIdMap.delete(error.signal)
      }
      return Promise.reject(error)
    }
  )

在網路上看過很多版本的用法,理念都是相同的都是使用axios中的CancelToken方法

  1. 在攔截器裡面統一在每次發送請求時,將請求加入至要取消地arry中

這個arry網上有其他作法是使用vuex來調用,但是對於我的項目來說vuex管理數據已經太龐大,後來又看到更簡單的做法是直接把arry掛在window下

window._axiosPromiseArr = [] // 全局聲明 (變數掛在window下)
    // http request 拦截器
axios.interceptors.request.use(
    config => {
        config.headers = {
            'Content-Type': 'application/json;charset=UTF-8'
        };
       // 每个请求都会 加入 
        config.cancelToken = new axios.CancelToken(cancel => {
      //  这个我习惯放再window 里面,也有配置再vuex里面的 感觉太麻烦了
            window._axiosPromiseArr.push({ cancel })

        })
        return config
    },
  1. 在main.js中調用全局的router.beforeEach

    每次跳轉路由前將之前掛載在window中的arry的請求全部中止,之後再將arry重新設置
router.beforeEach((to, from, next) => {
        window._axiosPromiseArr.forEach((el, index) => {
            el.cancel() // 路由跳转之前,中止请求
            //  重置 window._axiosPromiseArr
            delete window._axiosPromiseArr[index]
        })
        next();
    })

如果說有些請求是用來初始化或是其他業務需求而不能取消請求的,那麼只要加個判斷條件即可

axios.interceptors.request.use(
    config => {
        config.headers = {
            'Content-Type': 'application/json;charset=UTF-8'
        };
       // 每个请求都会 加入 
       if (config.headers.cancelRequest !== false){
        config.cancelToken = new axios.CancelToken(cancel => {
      //  这个我习惯放再window 里面,也有配置再vuex里面的 感觉太麻烦了
            window._axiosPromiseArr.push({ cancel })

        })
       }
        return config
    },

在API管理的地方加入條件就大功告成啦

axios.post('/user', null, {
  headers: {
    cancelRequest: false
  }
});

轉載至 : vue 路由切换时 中止未完成的请求 BY aInkFish

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值