如何确定函数链式调用优先级?实现LazyMan的sleepFirst优先执行
解决LazyMan的sleepFirst优先级问题
问题分析
你的代码当前存在两个核心问题:
- 所有操作都是立即执行,没有任务队列调度执行顺序,导致sleepFirst无法插队优先执行。
- 复用Array原型实现链式调用的方式不合适,无法区分任务优先级。
要实现sleepFirst无论调用顺序如何都优先执行,需要通过任务队列+异步调度控制执行顺序:将sleepFirst任务插入队列头部,其他任务按调用顺序加入队列尾部,最后按队列顺序异步执行所有任务。
修复后的代码
const LazyMan = (name, logFn) => { const taskQueue = []; // 将初始问候加入任务队列 taskQueue.push(() => logFn(`Hi, I'm ${name}.`)); // 异步调度器:按顺序执行队列中的所有任务 const runTasks = async () => { for (const task of taskQueue) { await task(); } }; // 延迟启动调度,确保所有链式调用的任务都先加入队列 setTimeout(runTasks, 0); // 返回支持链式调用的实例对象 return { sleepFirst(time) { // 将sleepFirst任务插入队列最前端,保证优先执行 taskQueue.unshift(async () => { await new Promise(resolve => setTimeout(resolve, time * 1000)); logFn(`Wake up after ${time} seconds.`); }); return this; }, eat(food) { taskQueue.push(() => logFn(`Eat ${food}`)); return this; }, sleep(second) { taskQueue.push(async () => { await new Promise(resolve => setTimeout(resolve, second * 1000)); logFn(`Wake up after ${second} seconds.`); }); return this; } }; }; // 测试调用 LazyMan('Ashish', console.log).eat('apple').sleep(10).sleepFirst(20);
代码说明
- 任务队列管理:所有操作(问候、eat、sleep、sleepFirst)都作为任务加入队列,sleepFirst通过
unshift插入队列头部,确保优先级。 - 异步调度:使用
async/await处理sleep的延迟逻辑,保证任务按顺序执行(上一个任务完成后才执行下一个)。 - 延迟启动调度:通过
setTimeout(runTasks, 0)让浏览器先处理完所有链式调用的任务添加,再开始执行队列中的任务,避免初始问候提前执行。
输出结果
执行后会得到期望的顺序:
Wake up after 20 seconds. Hi, I'm Ashish. Eat apple Wake up after 10 seconds.
内容的提问来源于stack exchange,提问作者Ashish Madaan
相关产品推荐
相关产品推荐

