axios之cancelToken取消多次重復請求

一、我們?yōu)槭裁葱枰∠?/h3>

我們常見的業(yè)務場景有,用戶頻繁點擊數(shù)據(jù)提交,用戶頻繁的切換數(shù)據(jù)量大的表格,在網(wǎng)絡較差的環(huán)境下,會出現(xiàn)一些異常的情況,當然,各類UI庫提供的loading狀態(tài)可以幫我們解決以上煩惱,以及可以通過防抖解決部分問題,但是我們今天從另一個方面,使用axios的cancelToken取消上次重復的請求。

二、我們怎樣取消?

先看一下aixos官方文檔的cancelToken的代碼

方法1:可以使用 CancelToken.source 工廠方法創(chuàng)建 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 參數(shù)是可選的)
source.cancel('Operation canceled by the user.');

方法2:還可以通過傳遞一個 executor 函數(shù)到 CancelToken 的構(gòu)造函數(shù)來創(chuàng)建 cancel token:

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函數(shù)接收一個 cancel 函數(shù)作為參數(shù)
    cancel = c;
  })
});

// cancel the request
cancel();

如何在我們項目中使用呢?

我們項目中,更常用的做法是在攔截器interceptors中使用。

當然,我們需要先定義一個map對象用于存儲相關值(map為es6新增對象,如果你對es6不了解,請查閱阮一峰的ECMAScript 6 入門

// 用于存儲pending的請求(處理多條相同請求)
const pendingRequest = new Map()

其次,需要封裝一些輔助類的函數(shù)

  • generateRequestKey 將重復的請求生成一個唯一的key
import qs from 'qs'
// 生成request的唯一key
const generateRequestKey = (config = {}) => {
  // 通過url,method,params,data生成唯一key,用于判斷是否重復請求
  // params為get請求參數(shù),data為post請求參數(shù)
  const { url, method, params, data } = config
  return [url, method, qs.stringify(params), qs.stringify(data)].join('&')
}
  • addPendingRequest將重復的請求,保存到到pendingRequest
// addPendingRequest 將重復請求添加到pendingRequest中
const addPendingRequest = (config) => {
  const key = generateRequestKey(config)
  if (!pendingRequest.has(key)) { //判斷pendingRequest中是否存在key
    config.cancelToken = new axios.CancelToken(cancel => {
      pendingRequest.set(key, cancel) //將key和cancel以鍵值對的方式保存
    })
  }
}
  • 將重復的請求取消,并在pendingRequest中刪除
// removePendingRequest 取消重復請求
const removePendingRequest = (config) => {
  const key = generateRequestKey(config)
  if (pendingRequest.has(key)) { //判斷pendingRequest中是否存在key
    const cancelToken = pendingRequest.get(key)
    cancelToken(key) // 取消之前發(fā)送的請求
    pendingRequest.delete(key)// 請求對象中刪除requestKey
  }
}

完整代碼

import axios from 'axios'
import qs from 'qs'

// 用于存儲pending的請求(處理多條相同請求)
const pendingRequest = new Map()

// 生成request的唯一key
const generateRequestKey = (config = {}) => {
  // 通過url,method,params,data生成唯一key,用于判斷是否重復請求
  // params為get請求參數(shù),data為post請求參數(shù)
  const { url, method, params, data } = config
  return [url, method, qs.stringify(params), qs.stringify(data)].join('&')
}

// 將重復請求添加到pendingRequest中
const addPendingRequest = (config) => {
  const key = generateRequestKey(config)
  if (!pendingRequest.has(key)) {
    config.cancelToken = new axios.CancelToken(cancel => {
      pendingRequest.set(key, cancel)
    })
  }
}

// 取消重復請求
const removePendingRequest = (config) => {
  const key = generateRequestKey(config)
  if (pendingRequest.has(key)) {
    const cancelToken = pendingRequest.get(key)
    cancelToken(key) // 取消之前發(fā)送的請求
    pendingRequest.delete(key)// 請求對象中刪除requestKey
  }
}

// 請求攔截器
service.interceptors.request.use(
  config => {
    // 處理重復請求
    removePendingRequest(config)
    addPendingRequest(config)

    return config
  },
  error => {
    // 處理請求錯誤
    return Promise.reject(error)
  }
)

// 響應攔截器
service.interceptors.response.use(
  response => {
    // 移除重復請求
    removePendingRequest(response.config)
    
    return res
  },
  error => {
    // 異常情況console,方便排查問題
    console.log('error', error)
    // 移除重復請求
    removePendingRequest(error.config || {})
    
    return Promise.reject(error)
  }
)

三、結(jié)尾

代碼中如有需要更正和修改的地方,歡迎評論留言,我也會積極回復。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • CancelToken 介紹 ? axios中用于取消請求的方法 使用 可以使用 CancelToken.so...
    帶刀打天下閱讀 2,489評論 0 1
  • 在 Web 項目開發(fā)過程中,我們經(jīng)常會遇到重復請求的場景,如果系統(tǒng)不對重復的請求進行處理,則可能會導致系統(tǒng)出現(xiàn)各種...
    桃花谷主V閱讀 495評論 0 0
  • 在開發(fā)中,經(jīng)常會遇到接口重復請求導致的各種問題。 對于重復的get請求,會導致頁面更新多次,發(fā)生頁面抖動的現(xiàn)象,影...
    zhao_ran閱讀 3,061評論 0 14
  • 在實際開發(fā)中,我們需要對用戶發(fā)起的重復請求進行攔截處理,比如用戶快速點擊提交按鈕。 對于重復的 get 請求,會導...
    前端技術(shù)驛站閱讀 2,131評論 0 1
  • 首先介紹下自己的背景: 我11年左右入市到現(xiàn)在,也差不多有4年時間,看過一些關于股票投資的書籍,對于巴菲特等股神的...
    瞎投資閱讀 5,944評論 3 8

友情鏈接更多精彩內(nèi)容