前端遇到高并发如何解决重复请求
在前端开发中遇到高并发场景时,若不加控制容易出现重复请求,这可能导致接口压力增加、数据异常、用户体验变差等问题。以下是前端防止/解决重复请求的常见方法,按不同场景归类总结:
🌟 一、常见重复请求场景
- 用户频繁点击按钮:多次触发相同请求(例如提交表单、下载操作)。
- 路由短时间内多次跳转或刷新:导致重复加载数据。
- 多次调用 debounce/throttle 未正确控制函数执行时机。
- 轮询或 WebSocket 消息导致并发访问同一接口。
🚀 二、常用解决方案
✅ 1. 禁用按钮防止多次点击
const [loading, setLoading] = useState(false);
const handleClick = async () => {
if (loading) return;
setLoading(true);
try {
await fetchData();
} finally {
setLoading(false);
}
};
<Button loading={loading} onClick={handleClick}>提交</Button>
✅ 2. 使用请求缓存 + Map 记录请求状态
原理:在请求发出前先检查是否已有相同请求在进行。
const requestCache = new Map();
const requestWithDeduplication = (url: string, options: any = {}) => {
if (requestCache.has(url)) {
return requestCache.get(url); // 复用已有请求
}
const req = fetch(url, options).finally(() => {
requestCache.delete(url); // 请求结束后清除缓存
});
requestCache.set(url, req);
return req;
};
适合统一封装
fetch
、axios
请求,避免相同参数的并发请求。
✅ 3. 使用 Axios 的 CancelToken 取消上一次请求
let controller: AbortController | null = null;
const request = async (url: string) => {
if (controller) {
controller.abort(); // 取消上一个请求
}
controller = new AbortController();
try {
const res = await fetch(url, { signal: controller.signal });
return await res.json();
} catch (e) {
if (e.name === 'AbortError') {
console.log('Request canceled');
}
}
};
适合搜索联想、快速切换 tab 等需要 只保留最后一次请求 的场景。
✅ 4. 使用 debounce/throttle 防抖节流
import { debounce } from 'lodash';
const fetchData = debounce((params) => {
// 实际请求
}, 300);
<input onChange={(e) => fetchData(e.target.value)} />
控制高频输入类请求频率,减少并发请求量。
✅ 5. 后端幂等 + 前端唯一请求 ID(可选高级方案)
- 给每次请求生成唯一 ID(如 UUID),发送给后端。
- 后端对相同 ID 请求只处理一次。
- 前端避免再做复杂状态判断,适合交易、支付类场景。
🧠 小结对照表
场景 | 推荐方案 |
---|---|
按钮多次点击 | 禁用按钮 / loading 状态 |
相同请求并发 | 请求缓存 Map / Axios CancelToken |
输入频繁调用接口 | debounce 防抖 |
只保留最后一个请求 | AbortController / CancelToken |
表单提交 /交易请求幂等 | 请求唯一 ID + 后端幂等处理 |
如果你告诉我你遇到的具体是哪个页面或场景(例如点击下载、搜索联想、多 tab 切换等),我可以给出更加定制化的解决方案。
作者:光影少年
来源:juejin.cn/post/7507560729609830434
来源:juejin.cn/post/7507560729609830434