Node.js async.parallelLimit 与 async.eachLimit 的区别与不同使用场景

概述

async.parallelLimit 方法在文档中位于 Controll Flow 章节,表明这个方法是用来做流程控制的,async.eachLimit 方法位于 Collections 章节,表明这个方法是用来做数据处理的。在实际开发中我们可以使用这两个方法来完成同样的工作,下面我们就以给 26 位用户发送邮件这个任务来举例。

使用 async.parallelLimit 方法实现

async.parallelLimit 方法接受两个参数,第一个参数为任务数组,每个任务是一个函数,第二个参数为每次并行执行的任务数,第三个参数为回调函数。使用 async.parallelLimit 完成发送邮件任务的思路是先使用数据与所要做的任务,组装成任务数组交给 async.parallelLimit 方法去执行。

let userEmailList = [ 'a@example.com', 'b@example.com', ..., 'z@example.com' ];
let limit = 5;
let taskList = userEmailList.map(function (email) {
    return function (callback) {
        sendEmail(email, function (error, result) {
            return callback(error, result);
        });
    }
});
async.parallel(taskList, limit, function (error, result) {
    console.log(error, result);
});

使用 async.eachLimit 方法实现

async.eachLimit 方法接受四个参数,第一个参数为原始数据数组,第二个参数为每次并行处理的数据量,第三个参数为需要为数据进行的处理,第四个参数为回调函数。使用 async.eachLimit 完成发送邮件任务的思路是定义一个对数据进行处理的函数,然后使用 async.eachLimit 将处理函数应用所有数据上。

let userEmailList = [ 'a@example.com', 'b@example.com', ..., 'z@example.com' ];
let limit = 5;
let processer = function (email) {
    sendEmail(email, function (error, result) {
        return callback(error, result);
    });
}
async.eachLimit(userEmailList, limit, processer, function (error){
    console.log(error);
});

通过以上代码和 async 文档 可以看出 each 系列函数最终的回调函数是没有运行结果的,所以每一次 processor 中的结果需要另行存储处理。

总结

通过对比以上两种方案,很容易发现 async.parallelLimitasync.eachLimit 的区别与应用场景,async.parallelLimit 作为流程控制方法,应该应用于并发处理不同的任务并返回结果,async.eachLimit 作为数据处理方法,应该应用于并发地对一批数据进行相同的处理。所以显然对于给 26 为用户发送邮件这个任务应该使用 async.eachLimit 方法来实现。

在应用场景选择恰当的情况下很少使用到 async.parallelLimit 方法,使用 async.parallel 就可以了,毕竟任务数量不会非常巨大,不做限制一次性并行执行也不会有太大问题。但是如果使用不当,用作数据处理,数据的量级可能会非常巨大,如果不做并行数量限制显然是不可取的方式。

因为对于这两个方法理解地不够透彻,并且受到 Promise.all 使用方式的影响,很多历史代码中从未出现过 async.eachLimit,都是使用 async.parallelLimit 配合 map 笨拙的实现了功能,特此写下此篇文章作为记录。

2017-01-06 14:50146