防抖函数需用 Promise 或 Callback 透传回调执行结果:每次调用返回新 Promise,取消前 pending 并 resolve 最终执行结果;Callback 版本需兼容错误传递与 Promise 等待;返回值始终对应实际执行的那次调用,非最后一次调用。

防抖中回调函数本身是异步执行的,而防抖函数通常不返回值(或只返回清除定时器的函数),所以想拿到防抖后实际执行的回调结果,不能靠直接 return,得靠 Promise 或 Callback 机制把“执行完成后的产物”透传出来。
用 Promise 包装防抖,让调用方 await 结果
核心思路:每次调用防抖函数时,都返回一个 Promise;当防抖真正触发并执行原始回调后,用 resolve 把它的返回值(或执行结果)传出。注意要处理防抖被取消的情况(比如新任务覆盖旧任务),此时应 reject 或静默处理。
- 为每个调用生成唯一的 Promise + resolve/reject 句柄,存入闭包变量(如 pending)
- 每次新调用先 reject(或忽略)上一个 pending,再新建 Promise
- 在 setTimeout 触发时,执行原始回调,捕获其返回值(支持同步或 Promise 返回),然后 resolve
- 示例:搜索框输入防抖请求,你希望拿到 fetch 的响应数据,而不是只触发请求
用 Callback 参数接收结果,适合不支持 async/await 的环境
如果项目仍需兼容老环境,或逻辑天然以回调驱动(如 Node.js 流式处理),可在防抖函数签名中增加可选的 callback 参数。该 callback 在防抖真正执行完毕后调用,参数为 (error, result)。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- callback 应只在最终执行那次被调用一次,避免多次触发多次回调
- 原始回调若抛错,应捕获后传给 callback 的 error 参数
- 原始回调若返回 Promise,需 await 后再调用 callback,否则 result 可能是 pending 状态的 Promise
- 注意不要和防抖的 cancel 函数混淆——cancel 是中断未执行的任务,不触发 callback
避免常见陷阱:返回值不是“最后一次调用”的结果
防抖的本质是“等停止触发后再执行”,所以所谓“返回值”永远对应的是那一组连续触发中最后落地执行的那一次,而非最后一次调用防抖函数那次(后者可能被取消)。这一点在设计 Promise 链或错误重试逻辑时尤为关键。
- 不要假设“第 5 次调用防抖 → 一定能拿到第 5 次的参数结果”,实际可能是第 3 次的参数被执行了
- 如果需要严格按调用顺序获取结果,防抖就不适用,应考虑节流或队列化
- 调试时可在 resolve 前打印实际执行的参数,确认是否符合预期
封装建议:返回 Promise 的防抖函数可复用性强
相比 callback 版本,Promise 版更易与 async/await、Promise.all、重试逻辑(如 p-retry)等现代异步工具集成。推荐作为默认封装形式,必要时再提供 callback 兼容层。
- 导出函数可命名为 debounceAsync,明确语义
- 支持传入 options.delay、options.maxWait(带最大等待的防抖)、options.leading(首次立即执行)等扩展能力
- resolve 的值统一为原始回调的执行结果(自动 await 处理),reject 则用于取消或异常场景(可配选项开关)

















