1. スロットルの意味
1. フロントエンドがインターフェイスを呼び出すと、バックエンド インターフェイスがインターフェイスを通じて連続して複数回呼び出される場合があります。これにより、バックエンドの応答負荷が増加し、送信サービス データの帯域幅が占有され、その結果、資源の無駄遣い。
2. 実施方法
1. 一般的な実装では、キャッシュ キーと同じ URL、リクエスト メソッド、およびリクエスト パラメータが使用されます。インターフェイスがリクエストされるたびに、キーはキャッシュ オブジェクトに保存されます。インターフェイスの応答が完了すると、キーはキャッシュ オブジェクトから削除されます。キャッシュオブジェクト。
2. リクエスト送信時に、キーを使用してキャッシュオブジェクトから値を取得します。値が取得された場合、リクエストはリクエストされましたが完了していないため、リクエストは中断されます。
3. コードを実装する
1.新しいthrottleHttp.jsを作成します
// 新建map用于存放正在执行的请求
const pendingRequest = new Map()
class throttleHttp {
constructor(originalAxios) {
this.originalAxios = originalAxios
}
// generateReqKey:用于根据当前请求的信息,生成请求Key存放到map中作为当前请求的键;
generateReqKey(config) {
let { method, url, params, data } = config
if (typeof params === 'string') {
params = JSON.parse(params)
}
if (typeof data === 'string') {
data = JSON.parse(data)
}
// return [method, url.replace(config.baseURL, ''), JSON.stringify(params), JSON.stringify(data)].join('&')
return [method, url.replace(`${config.baseURL}/`, ''), JSON.stringify(params), JSON.stringify(data)].join('&')
}
// addPendingRequest:用于把当前请求信息添加到pendingRequest对象中
addPendingRequest(config) {
const requestKey = this.generateReqKey(config)
// 这下面的部分不能去除的原因是因为在清空所有请求的时候需要用到cancel令牌
// 所以必须在添加请求的时候就创建一个CancelToken取消令牌用于之后clearPending函数清空请求
const originalAxios = this.originalAxios
config.cancelToken = new originalAxios.CancelToken((cancel) => {
// 创建当前请求放到map中
pendingRequest.set(requestKey, cancel)
})
}
// 去除所有列表里的请求(用于跳转路由等需要清空请求的情况)
clearPending() {
// 遍历map对象,用每个取消令牌逐一取消请求,起到清空所有请求的作用
for (const [requestKey, cancelToken] of pendingRequest) {
cancelToken(requestKey)
}
// 清空map对象
pendingRequest.clear()
}
pendingReqHasKey(key) {
return pendingRequest.has(key)
}
pendingReqdelKey(key) {
pendingRequest.delete(key)
}
}
export default throttleHttp
2. カプセル化された axios で throttleHttp.js を参照する
import axios from 'axios'
/* eslint-disable */
const ThrottleHttp = new throttleHttp(axios)
axios.defaults.timeout = 86400000
axios.defaults.baseURL = basePublicUrl
axios.defaults.withCredentials = false
axios.defaults.headers.post['Content-Type'] = 'application/json'
// 如果走全局网关,看是否进行加密
// 请求拦截
axios.interceptors.request.use(function (config) {
// 生成请求key
const requestKey = ThrottleHttp.generateReqKey(config)
if (ThrottleHttp.pendingReqHasKey(requestKey)) {
return httpMark
}
// 把当前请求信息添加到pendingRequest对象中
ThrottleHttp.addPendingRequest(config)
return config
}, function (error) {
// 这里出现错误可能是网络波动造成的,清空 pendingRequests 对象
ThrottleHttp.clearPending()
return Promise.reject(error.response)
})
axios.interceptors.response.use(function (response) {
// 删除收集的请求key
const requestKey = ThrottleHttp.generateReqKey(response.config)
// 根据key删除当前请求
ThrottleHttp.pendingReqdelKey(requestKey)
// 收集报错信息
return response
}, function (error) {
// 删除收集的请求key
const requestKey = ThrottleHttp.generateReqKey(error.config)
//根据key删除当前请求
ThrottleHttp.pendingReqdelKey(requestKey)
return error
})