Node.js并发控制机制代码疑问:为何回调中需调用next()
代码示例
const tasks = ... let concurrency = 2; let running = 0; let completed = 0; let index = 0; function next() { while (running < concurrency && index < tasks.length) { const task = tasks[index++]; task(() => { if (completed === tasks.length) { return finish(); } completed++; running--; next(); }); running++; } } next(); function finish() { console.log('All tasks are done'); }
用户疑问
我对上述Node.js并发控制代码存在疑问:tasks是需执行的异步任务数组,concurrency为最大并发数。程序启动时会取出前两个任务执行,当某个任务完成后会触发其回调函数。请问为何要在该回调中再次调用next()?回调执行完毕后,当前next()中的循环难道不会再次检查是否要取下一个任务处理吗?
解答
核心原因是第一次调用的next()里的循环会直接跑完,不会等待异步任务完成。
具体来说:
- 程序启动调用
next()后,会立刻进入while循环:先取第一个任务执行,running变为1;接着取第二个任务执行,running变为2。此时running不小于并发数2,循环直接结束,next()函数执行完毕退出,不会停在那里等任务完成。 - 当某个异步任务完成触发回调时,之前的
next()早就执行完了,根本不会再去检查循环条件。这时候必须手动调用next(),重新触发while循环:- 回调里先把
running减1(比如从2变回1),此时running < concurrency的条件重新满足 - 调用
next()后,循环会检查是否还有未执行的任务(index < tasks.length),如果有就取出下一个任务执行,同时running加1,直到再次填满并发数或者任务全部取完
- 回调里先把
举个实际例子:假设tasks有3个任务。第一次next()执行完,前两个任务在跑,running=2,循环停了。等第一个任务完成,回调里running减到1,调用next(),循环会取出第三个任务执行,running变回2,循环再次结束。等剩下的任务完成时,回调里调用next(),循环会因为index等于tasks长度而不执行,直到最后一个任务完成触发finish()。
如果不在回调里调用next(),第一次next()跑完后,剩下的任务永远不会被执行——因为没人再去触发那个while循环了。
内容的提问来源于stack exchange,提问作者davaer
相关产品推荐
相关产品推荐

