如何改造JS限流函数,通过Promise获取被延迟执行函数的返回值
问题原因
你之前实现的Promise版本仅第一次返回Promise的核心原因是:当任务正在执行(isCalled=true)时,schedule函数不会进入if (canSchedule)分支,没有返回值,后续调用拿到的就是undefined,自然无法链式调用then获取结果。
改造后的实现
function rateLimter(fn, wait) { const queue = [] let isCalled = false const schedule = async function () { const canSchedule = queue.length && !isCalled if (canSchedule) { isCalled = true // 取出队列里存的任务信息:绑定好的原函数、resolve、reject const { task, resolve, reject } = queue.shift() try { // 等待原函数执行完成,支持异步函数 const result = await task() resolve(result) } catch (err) { // 异常处理 reject(err) } finally { setTimeout(() => { isCalled = false schedule() }, wait) } } } return function (...args) { // 每次调用直接返回Promise,保证调用方一定能拿到Promise实例 return new Promise((resolve, reject) => { // 把任务和对应的resolve/reject一起存入队列 queue.push({ task: fn.bind(this, ...args), resolve, reject }) schedule() }) } }
核心改造点
- 每次调用限流包装后的函数时,直接创建Promise实例返回,不管当前是否有正在执行的任务,都能保证调用方拿到Promise对象可以链式调用
then/catch - 队列中存储的不再是单独的绑定后函数,而是同时携带对应Promise的
resolve和reject方法,任务执行完成后直接调用对应方法传递结果 - 新增异常处理逻辑,原函数执行抛出的错误可以通过
catch捕获 - 支持异步原函数,会等待原函数执行完成后再传递返回值
使用你提供的测试用例运行时,会按照1秒间隔依次输出10、11、12,符合预期。
内容的提问来源于stack exchange,提问作者Joji
相关产品推荐
相关产品推荐

