我們在開發時 經常會遇到類似場景
- 提交表單時,連續點擊提交表單,導致後臺重複處理
- 寫一個連續點擊腳本,不停發送請求,併發量導致服務器癱瘓
今天,我們解決類似問題:
一、重複請求
處理流程:
代碼:
request.js
引入請求以及部分組件,並且定義一個變量用來存儲請求url
import axios from 'axios'
import { Message, Notification } from 'element-ui'
let requestList = new Set() // 存儲請求url
請求發出前,利用攔截器判斷當前是否存在請求,如果存在利用cancelToken取消,反之添加到數組中
// 請求前攔截器
axios.interceptors.request.use(config => {
// 利用cancelToken 取消當次請求
config.cancelToken = new axios.CancelToken(e => {
// 在這裏阻止重複請求,上個請求未完成時,相同的請求不會再次執行
requestList.has(config.url) ? e(`${location.host}${config.url}---重複請求被中斷`) : requestList.add(config.url)
})
return config
}, error => {
Message.error('未知錯誤')
return Promise.reject(error)
})
利用響應攔截器,在這裏處理已發送或者被動取消的請求
已發送請求無論成功與否,務必在數組中清除掉
這裏根據需求處理:
- 成功的業務邏輯
- 取消的業務邏輯
- 失敗的業務邏輯
// 響應攔截器
axios.interceptors.response.use(response => {
// 相同請求不得在600毫秒內重複發送,反之繼續執行
setTimeout(() => {
requestList.delete(response.config.url)
}, 600)
// 請求成功業務邏輯
if (response.data.code == '200') {
return response.data
} else {
switch (response.data.code) {
case 201:
Message.warning('您提交的信息異常')
break
case 203:
Notification({
title: '提示',
message: response.data.msg,
type: 'error',
showClose: true,
})
router.replace({path: '/login'})
break;
default:
Message.error(response.data.msg)
}
}
}, error => {
// 這裏判斷異常情況,如果axios.isCancel 爲 true時,說明請求被取消
if (axios.isCancel(error)) {
// 請求取消
console.warn(error)
console.table([error.message.split('---')[0]], 'cancel')
} else {
// 請求失敗
if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {
Message.warning('請求超時')
} else if (error.message == 'Network Error') {
Message.error('網絡連接異常,請重試')
} else {
Message.error('未知錯誤', error.message)
}
// 請求如果失敗了,務必從列表裏面刪掉,否則請求攔截器會取消請求
requestList.delete(error.config.url)
}
return Promise.reject(error)
})
總結:
- 請求攔截器
利用數組存儲每次發出請求url,請求攔截器判斷數組是否存在此次請求url,如果存在,調用cancelToken取消請求並且清除url,反之url添加到數組中 - 響應攔截器
本次請求不論成功與否,清除本次url記錄,否則會攔截取消請求
- 注意:
- 可以使用同一個 cancel token 取消多個請求
效果:
至此,我們就成功攔截了重複請求
鏈接: