import axios from "axios";// 1. 緩存已完成的請求結果(key:請求URL+參數,value:數據)
const requestCache = new Map();
// 2. 記錄正在執行的請求(避免并行重復請求)
const pendingRequests = new Set();// 請求攔截器:發起請求前檢查
axios.interceptors.request.use(config => {// 生成請求唯一標識(URL + 方法 + 參數)const requestKey = `${config.url}-${config.method}-${JSON.stringify(config.params)}`;// 情況1:請求正在執行中,攔截新請求if (pendingRequests.has(requestKey)) {return Promise.reject(new Error("當前請求已在執行,請勿重復觸發"));}// 情況2:請求已緩存,直接返回緩存數據(不發新請求)if (requestCache.has(requestKey)) {return Promise.resolve({ data: requestCache.get(requestKey) });}// 情況3:新請求,加入“正在執行”列表pendingRequests.add(requestKey);return config;
});// 響應攔截器:請求完成后更新緩存/狀態
axios.interceptors.response.use(response => {const requestKey = `${response.config.url}-${response.config.method}-${JSON.stringify(response.config.params)}`;// 1. 緩存請求結果requestCache.set(requestKey, response.data);// 2. 從“正在執行”列表移除pendingRequests.delete(requestKey);return response;},error => {// 錯誤時也移除“正在執行”狀態const requestKey = `${error.config.url}-${error.config.method}-${JSON.stringify(error.config.params)}`;pendingRequests.delete(requestKey);return Promise.reject(error);}
);// 調用示例:相同參數的請求,短時間內只發一次
function fetchStyle() {axios.get("/api/page-style", { params: { theme: "light" } }).then(res => console.log("樣式數據(緩存/新請求):", res.data)).catch(err => console.log("請求攔截:", err.message));
}// 1秒內調用3次,只發1次請求,后2次用緩存
fetchStyle();
setTimeout(fetchStyle, 500);
setTimeout(fetchStyle, 800);
這個地方的set和map使用,為什么不用對象和數組?
- 用普通對象 {} 替代 Map:
可行,但鍵只能是字符串 / Symbol,且判斷鍵是否存在需要用 obj.hasOwnProperty(key)(不如 map.has(key) 直觀)。 - 用數組 [] 替代 Set:
可行,但檢查是否存在需要 array.includes(key)(O (n) 復雜度,數據量大時效率低),且需要手動去重(if (!array.includes(key)) array.push(key))。