为何此Promise始终无法resolve?Promise队列代码异常排查
为什么第一段Promise队列代码失效,第二段正常?
核心原因
第一段代码的无限同步循环彻底阻塞了Node.js的事件循环,导致异步任务的回调完全无法执行;第二段通过await主动让出事件循环,让异步回调有机会运行,从而实现了预期的队列逻辑。
第一段代码的问题分析
第一段的run函数是无任何异步等待的死循环:
const run = async () => { while (true) { if (currentQueueSize <= maxQueueSize) { console.log('current queue size ', currentQueueSize); requestData(); } } };
虽然函数标记了async,但内部没有await语句,整个循环会同步占用Node.js的单线程,直到无限运行下去。
Node.js基于事件循环模型工作:同步代码会优先占用线程,只有同步代码执行完毕,才会处理异步任务的回调(比如Promise的then/finally、网络请求回调等)。在这段代码里:
- 循环会疯狂调用
requestData(),把currentQueueSize快速推到超过maxQueueSize - 事件循环被死循环完全卡死,队列中
axios.get的Promise完成后,对应的then/finally回调永远无法进入事件循环的执行队列,自然不会被执行。
第二段代码的修复原理
第二段的run函数在队列满时加入了await逻辑:
await new Promise((resolve, _reject) => { const waiter = () => setTimeout(() => { if (currentQueueSize <= maxQueueSize) { console.log(`Queue size ${currentQueueSize} now under max queue size of ${maxQueueSize}, resuming...`); resolve(true); } else { console.log(`Waiting for queue size to reduce, current queue size ${currentQueueSize}`); waiter(); } }, 1000); waiter(); });
await的核心作用是暂停当前async函数的执行,把线程交还给事件循环,去处理其他待执行的任务:
- 当队列满时,
await触发定时器并让出事件循环,此时之前队列中axios.get的Promise回调(then/finally)终于能被执行,currentQueueSize会正确递减。 - 定时器每1秒检查一次队列大小,当队列回到阈值内时,
resolvePromise,run函数的循环继续执行,添加新任务。
内容的提问来源于stack exchange,提问作者Bruno Brito
相关产品推荐
相关产品推荐

