关于Nodejs async模块的eachLimit方法的疑问

关于Nodejs async模块的eachLimit方法的疑问

感觉你是对的. 稍微修改下作者的代码, 也可以验证:

var async = require('async');

var arr = [{name:'#1', delay: 100},   // 修改了下delay的值
           {name:'#2', delay: 800},    // #2 的delay 设置得较长
           {name:'#3', delay: 100},
           {name:'#4', delay: 200},
           {name:'#5', delay: 300},
           {name:'#6', delay: 400}];

var t = new Date();  // 记录个时间
async.eachLimit(arr, 2, function(item, callback) {
    log('1.5 enter:  ' + item.name + ' - ' + item.delay);
    setTimeout(function(){
        log('1.5 handle: ' + item.name);
        callback(null, item.name);
    }, item.delay);
}, function(err) {
    log('1.5 err: ' + err);
});

function log(msg) {
  console.log('%s> %s', pad(new Date() - t, 4), msg);
}

function pad(n, width, z) {  // 前缀一些'0'
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

程序输出为:

0007> 1.5 enter: #1 - 100 0009> 1.5 enter: #2 - 800 0110> 1.5 handle: #1 0110> 1.5 enter: #3 - 100 0211> 1.5 handle: #3 0212> 1.5 enter: #4 - 200 0412> 1.5 handle: #4 0412> 1.5 enter: #5 - 300 0713> 1.5 handle: #5 0713> 1.5 enter: #6 - 400 0810> 1.5 handle: #2 1114> 1.5 handle: #6 1115> 1.5 err: undefined

可以看到#2在队列中很久, #3, #4和#5都执行完后, #2才执行完.


2 回复

关于Node.js async模块的eachLimit方法的疑问

在使用Node.js的async模块时,eachLimit 方法是一个非常有用的工具,它可以限制并发执行的任务数量。下面我们将通过一个具体的例子来理解 eachLimit 方法的工作原理。

示例代码

var async = require('async');

var arr = [
    {name:'#1', delay: 100},   // 修改了下delay的值
    {name:'#2', delay: 800},    // #2 的delay 设置得较长
    {name:'#3', delay: 100},
    {name:'#4', delay: 200},
    {name:'#5', delay: 300},
    {name:'#6', delay: 400}
];

var t = new Date();  // 记录个时间
async.eachLimit(arr, 2, function(item, callback) {
    log('1.5 enter:  ' + item.name + ' - ' + item.delay);
    setTimeout(function(){
        log('1.5 handle: ' + item.name);
        callback(null, item.name);
    }, item.delay);
}, function(err) {
    log('1.5 err: ' + err);
});

function log(msg) {
  console.log('%s> %s', pad(new Date() - t, 4), msg);
}

function pad(n, width, z) {  // 前缀一些'0'
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

输出结果

0007> 1.5 enter:  #1 - 100
0009> 1.5 enter:  #2 - 800
0110> 1.5 handle: #1
0110> 1.5 enter:  #3 - 100
0211> 1.5 handle: #3
0212> 1.5 enter:  #4 - 200
0412> 1.5 handle: #4
0412> 1.5 enter:  #5 - 300
0713> 1.5 handle: #5
0713> 1.5 enter:  #6 - 400
0810> 1.5 handle: #2
1114> 1.5 handle: #6
1115> 1.5 err: undefined

解释

  • 并发限制eachLimit 方法的第一个参数是数组,第二个参数是并发限制的数量(这里是2)。这意味着在任何时刻,最多只有两个任务会被同时处理。

  • 任务执行顺序:尽管 #2 的延迟较长(800ms),它仍然会在 #1 执行完毕之后立即被加入到队列中。但由于并发限制为2,#3#4#1#2 之后立即被添加到队列中,并且在 #2 完成之前就完成了处理。

  • 完成顺序:从输出结果可以看出,#2 被推迟了一段时间(直到 #3, #4, 和 #5 都完成后),因为它受到并发限制的影响。

通过这个例子,我们可以看到 eachLimit 方法如何有效地管理并发任务,确保不会因为某些任务的延迟而导致其他任务被长时间阻塞。


async.eachLimit 方法是 async 库中的一个函数,它允许你在给定数组上并行执行任务,并且可以限制同时运行的任务数量。这样可以防止因同时处理大量任务而导致的性能问题或资源耗尽。

根据你提供的代码和描述,async.eachLimit 正确地限制了并发的任务数为2。这意味着在任何时候最多有两个任务在并行执行。一旦其中一个任务完成,下一个任务才会开始执行。

在你的例子中,当数组中的每个对象被处理时,它会模拟延迟(通过 setTimeout)。由于 async.eachLimit 将并发数限制为2,第一个两个任务(即处理 #1#2 的任务)几乎同时开始执行。然而,由于 #2 的延迟时间更长(800毫秒),因此它比其他任务花费的时间更长。这导致在 #2 完成之前,其他的任务(如 #3, #4, #5)已经开始并完成它们的工作。

最终,所有任务都被处理完毕,async.eachLimit 回调函数在所有任务完成后被调用,错误参数 errundefined,表示没有发生错误。

以下是对这段代码的简化解释:

  • 限制并发数:通过设置 async.eachLimit 的第三个参数为2,确保同时最多只有两个任务在运行。
  • 任务执行顺序:尽管 #2 的延迟最长,但一旦前两个任务启动,后续任务会立即排队等待,直到前面的任务完成。
  • 输出结果:从输出可以看到,尽管 #2 最后完成,但由于 async.eachLimit 控制了并发度,任务依然按照预期顺序依次处理完成。

如果你有任何具体的疑问或需要进一步说明的地方,请告诉我!

回到顶部