You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中p-queue并发限制下计数器值异常问题求助

问题根源与解决方案:p-queue并发任务中计数器值异常

问题本质

这是JavaScript中闭包与var变量作用域的经典陷阱,和p-queue本身无关。

为什么无并发限制时正常?

无并发限制下,queue.add()的任务会被立即执行,此时循环里的i还没进入下一次迭代,闭包能捕获到当前迭代的i值,所以输出正常。

为什么设置并发后出现异常?

当设置并发数为2时,前2个任务立即执行,剩余任务被放入队列等待。而var声明的i是函数级作用域,整个循环共享同一个i的引用——循环会在所有等待任务执行前就跑完,此时i已经变成了循环结束后的6,所以后续任务执行时,闭包捕获的就是这个最终值。

解决方案

方案1:将var替换为let(推荐)

let是块级作用域,每次循环都会创建一个独立的i变量,闭包捕获的是当前迭代块的i,不会受后续循环影响:

import PQueue from 'p-queue';
console.time('bunch-of-stuff');

var queue = new PQueue({concurrency: 2});

// 把var改为let
for (let i = 1; i <= 5; i++) {
    console.log(i);
    queue.add(() => httpProcess(i));
}

console.timeEnd('bunch-of-stuff');

function httpProcess(pageNumber) {  
    console.log('Done: ' + pageNumber);
}

执行后输出会恢复正常:

1
Done: 1
2
Done: 2
3
4
5
bunch-of-stuff: [时间]ms
Done: 3
Done: 4
Done: 5

方案2:使用立即执行函数(IIFE)创建独立作用域

如果因为兼容等原因不能用let,可以用IIFE把当前迭代的i值封装到独立作用域中:

import PQueue from 'p-queue';
console.time('bunch-of-stuff');

var queue = new PQueue({concurrency: 2});

for (var i = 1; i <= 5; i++) {
    console.log(i);
    // 用IIFE捕获当前i值
    queue.add((function(num) {
        return () => httpProcess(num);
    })(i));
}

console.timeEnd('bunch-of-stuff');

function httpProcess(pageNumber) {  
    console.log('Done: ' + pageNumber);
}

内容的提问来源于stack exchange,提问作者Stephen Case

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:50:20