promise点击防刷器核心是控制重复点击对应操作的执行时机:1. 请求锁机制复用pending promise;2. 队列式节流按序执行;3. abortcontroller可取消旧请求;4. 冷却期+promise组合优化体验。

用 Promise 设计点击防刷器,核心是让重复点击在“前一次请求未完成时”自动排队或忽略,而不是并发发出多个请求。关键不是阻止点击本身,而是控制后续点击对应的操作(如 API 调用)是否立即执行、等待、或取消。
1. 基于 Promise 状态的请求锁机制
维护一个正在执行的 Promise(比如上次点击触发的 fetch),新点击时检查它是否 pending:如果是,就复用它;否则发起新请求。
- 适合场景:按钮点击后发请求,用户手快连点,希望只发一次,且后续点击能拿到相同结果
- 实现要点:用闭包或模块变量保存当前 pending 的 Promise,每次点击返回同一个 Promise 实例(不 new Promise)
- 示例逻辑:
let currentRequest = null;
function clickHandler() {
if (currentRequest) {
return currentRequest; // 复用已有 Promise
}
currentRequest = fetch('/api/submit')
.then(res => res.json())
.finally(() => { currentRequest = null; }); // 完成后清空
return currentRequest;
}
2. 带队列的节流式防刷(支持多次点击有序执行)
如果希望多次点击不丢弃,而是按顺序执行(比如提交多条数据),可用 Promise 链式排队。
- 维护一个“执行链”,每次点击把新操作追加到上一个 Promise 的 then 后面
- 确保串行、无竞态,但不会阻塞 UI 或报错中断
- 代码示意:
let chain = Promise.resolve();
function queuedClick() {
chain = chain.then(() => fetch('/api/submit'))
.catch(err => console.warn('请求失败,不影响后续', err));
return chain;
}
3. 可取消的防刷(结合 AbortController + Promise.race)
对已发出但尚未响应的请求,支持在新点击时主动 abort 上一个,避免资源浪费。
- 适合耗时长、可中断的请求(如上传、搜索)
- 每次点击生成新 AbortController,用 Promise.race 判断是新请求胜出还是旧请求先完成
- 注意:需服务端配合支持 abort(如 fetch 默认支持)
4. 实用封装:带冷却期的防刷函数
纯前端体验优化,点击后禁用按钮一段时间(视觉防刷),同时配合 Promise 控制逻辑防刷。
- 冷却期(如 500ms)内忽略点击,不发请求也不排队
- 冷却期外才走 Promise 锁或队列逻辑
- 推荐组合使用:视觉禁用 + 请求级去重,体验和健壮性兼顾
不复杂但容易忽略:防刷目标不是“不让用户点”,而是“不让无效请求发出去”。Promise 在这里的作用是统一异步状态管理,让点击行为可预测、可复用、可衔接。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











