今日问题:防止接口重复调用的前端解决方案。
Q:在前端面试中,如果被问到,接口防止重复调用的前端解决方案都有哪些,什么回答比较好,全面、具体一些,尽量描述出所有细节和实现方案,给出必要的代码示例。
A:在前端面试中,谈论接口防止重复调用的解决方案时,可以从以下几个方面进行全面而具体的讨论:
js// 使用lodash的debounce函数来实现防抖
import _ from 'lodash';
function fetchData() {
// 触发请求的函数
}
// 防抖函数,等待300ms后执行
const debouncedFetchData = _.debounce(fetchData, 300);
// 在事件处理函数中使用
button.addEventListener('click', debouncedFetchData);
js// 使用lodash的throttle函数来实现节流
import _ from 'lodash';
function fetchData() {
// 触发请求的函数
}
// 节流函数,每1000ms内最多执行一次
const throttledFetchData = _.throttle(fetchData, 1000);
// 在事件处理函数中使用
button.addEventListener('click', throttledFetchData);
html<div id="app">
<button @click="sendRequest" :loading="loading">请求</button>
</div>
methods: {
async sendRequest() {
this.loading = true; // 禁用按钮
try { // 发送请求
await yourApiRequestFunction(); // 请求成功后,启用按钮
} catch (error) { // 处理错误情况 }
finally {
this.loading = false; // 请求完成后,启用按钮
}
},
}
jsconst pendingRequest = new Map();
function generateReqKey(config) {
const { method, url, params, data } = config;
return [method, url, Qs.stringify(params), Qs.stringify(data)].join("&");
}
function addPendingRequest(config) {
const requestKey = generateReqKey(config);
config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
if (!pendingRequest.has(requestKey)) {
pendingRequest.set(requestKey, cancel);
}
});
}
function removePendingRequest(config) {
const requestKey = generateReqKey(config);
if (pendingRequest.has(requestKey)) {
const cancelToken = pendingRequest.get(requestKey);
cancelToken(requestKey);
pendingRequest.delete(requestKey);
}
}
// axios拦截器代码
axios.interceptors.request.use(
function (config) {
removePendingRequest(config); // 检查是否存在重复请求,若存在则取消已发的请求
addPendingRequest(config); // 把当前请求信息添加到pendingRequest对象中
return config;
},
(error) => {
return Promise.reject(error);`
}
);
axios.interceptors.response.use(
(response) => {
removePendingRequest(response.config); // 从pendingRequest对象中移除请求
return response;
},
(error) => {
removePendingRequest(error.config || {}); // 从pendingRequest对象中移除请求
if (axios.isCancel(error)) {
console.log("已取消的重复请求:" + error.message);
} else {
// 添加异常处理
}
return Promise.reject(error);
}
);
jslet isFetching = false;
function fetchData() {
if (isFetching) return;
isFetching = true;
// 发起请求
fetch('/api/data')
.then(response => response.json())
.then(data => {
console.log(data);
isFetching = false;
})
.catch(() => {
isFetching = false;
});
}
button.addEventListener('click', fetchData);
jsconst cache = {};
function fetchData(params) {
const key = JSON.stringify(params);
if (cache[key]) {
return Promise.resolve(cache[key]);
}
return fetch('/api/data', { params })
.then(response => response.json())
.then(data => {
cache[key] = data;
return data;
});
}
jsconst requestQueue = [];
let isProcessing = false;
function processQueue() {
if (isProcessing || !requestQueue.length) return;
isProcessing = true;
const { url, params, resolve, reject } = requestQueue.shift();
fetch(url, { params })
.then(response => response.json())
.then(data => {
resolve(data);
isProcessing = false;
processQueue();
})
.catch(error => {
reject(error);
isProcessing = false;
processQueue();
});
}
function fetchData(url, params) {
return new Promise((resolve, reject) => {
requestQueue.push({ url, params, resolve, reject });
processQueue();
});
}
jsconst pendingRequests = new Set();
function fetchData(url, params) {
const key = `${url}_${JSON.stringify(params)}`;
if (pendingRequests.has(key)) {
return Promise.reject(new Error('Duplicate request'));
}
pendingRequests.add(key);
return fetch(url, { params })
.then(response => response.json())
.then(data => {
pendingRequests.delete(key);
return data;
})
.catch(error => {
pendingRequests.delete(key);
throw error;
});
}
jsfunction fetchData(url, params) {
const key = `fetch_${url}_${JSON.stringify(params)}`;
const cachedData = localStorage.getItem(key);
if (cachedData) {
return Promise.resolve(JSON.parse(cachedData));
}
return fetch(url, { params })
.then(response => response.json())
.then(data => {
localStorage.setItem(key, JSON.stringify(data));
return data;
});
}
jslet fetchPromise = null;
function fetchData() {
if (fetchPromise) return fetchPromise;
fetchPromise = fetch('/api/data')
.then(response => response.json())
.finally(() => {
fetchPromise = null;
});
return fetchPromise;
}
这些示例提供了不同策略的实现方式,可以根据具体需求进行选择和调整。
本文作者:CreatorRay
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!