Async使用简介之集合操作

 2015年05月21日    1032     声明


上篇文章介绍了Async流程控制部分常用的一些方法,在Node.js的异步编程模式中我们还经常遇到对集合处理的情况,Async提供了很处理集合的方法,方便我们对集合进行异步操作。本文将介绍一些Async中常用的集合操作方法。

在Async集合操作部分,常用的方法有:each、map、filter、reduce等。这些方法功能如下:

  • each:对集合中的每个数据进行异步处理
  • map:对集合中的每个数据进行异步处理后生成一个新值,并生成一个新值的集合
  • filter:对集合中的数据进行异步筛选
  • reduce:对集合中的数据进行处理后得到一个唯一的结果


1. each(arr, iterator(item, callback), callback(err))

对数组arr中的每一项执行iterator操作。iterator方法中会传一个当前执行的项及一个回调方法。each方法中所有对象是并行执行的。

参数

arr:要执行操作的数组。
iterator(item, callback):对arr中的对象执行的方法。调用callback方法后,表示本对象的处理操作。发生错误,即执行callback(err)回调,未执行完的项将被跳过,并将错误传入最终回调方法中。无错误则执行完毕后进行最终回调方法中。
callback(err):最终回调方法。出错后或全部执行完成后将进入此方法。

示例

// 假定openFiles为一个打开文件的数组
async.each(openFiles, function(file, callback) {
  // 对数组中的每个文件进行过滤
  console.log('Processing file ' + file);

  if( file.length > 32 ) {
    //抛出异常
    console.log('文件名太长');
    callback('File name too long');
  } else {
    // 对文件进行一些处理后回调进行下一个文件处理
    console.log('File processed');
    callback();
  }
}, function(err){
    // 如果文件集合中的任何一个文件出现错误,错误都会被传入err参数中
    if( err ) {
      // 集合中任意一个文件出错都将结束其后所有操作
      console.log('A file failed to process');
    } else {
      // 没有错误时,所有文件处理完成后进入此分支
      console.log('All files have been processed successfully');
    }
});

// iterator也可以写在外部
async.each(openFiles, saveFile, function(err){
});

//处理文件的方法
function saveFile(file, callback){
  
}

除each方法外Async还有几个对each方法的扩展,如:用于顺序执行的eachSeries方法和限制执行次数的eachLimit方法,不在详述,如有需要请自行参考Async API。


2. map(arr, iterator(item, callback), callback(err, results))

与each方法不同,map方法用于操作对象的转换,转换后的结果集会被传递至最终回调方法中。

参数

arr:要执行操作的数组。
iterator(item, callback):对arr中的对象执行的方法。调用callback(err, transformed)方法后,进入下一个对象的操作。发生错误,即执行callback(err)回调,未执行完的项将被跳过,并将错误传入最终回调方法中。无错误则执行callback(null, transformed),将转换对象传递至结果集results中。
callback(err, results):最终回调方法。出错后或全部执行完成后将进入此方法。

示例

async.each(['file1','file2','file3'], function(file, callback) {
  // 对数组中的每个文件进行一些处理

  if( file.length > 32 ) {
    //抛出异常
    console.log('文件名太长');
    callback('File name too long');
  } else {
    // 对文件进行一些处理后回调进行下一个文件处理
    console.log('File processed');
    callback();
  }
}, function(err, results){
    // 如果文件集合中的任何一个文件处理出现错误,错误都会被传入err参数中
    if( err ) {
      // 集合中任意一个文件出错都将结束其后所有操作
      console.log('A file failed to process');
    } else {
      // 没有错误时,所有文件处理完成后的新文件都被传递至results中
      console.log(results);
    }
});

map也是一个并行执行的方法,如需要顺序执行请使用mapSeries方法。其它map相关方法请参考Async API


3. filter(arr, iterator(item, callback(truthValue)), callback(results))

filter用于对集合中的元素进行筛选。iterator的callback只有一个参数,参数为true或false的boolean型数据。 filter没有提供错误处理方法,出错后将由nodejs直接报错,使用时要注意自行处理错误。

参数

arr:要执行操作的数组。
iterator(item, callback):对arr中的对象执行过滤的方法。执行完成后执行callback(truthValue)回调方法后完成本次过滤。
callback(results):最终回调方法。results为符合过滤后的数据。

示例

async.each(['file1','file2','file3'], function(file, callback) {
  // 对数组中的每个文件进行过滤
  if( file.length > 32 ) {
    //不符合条件回调false
    callback(false);
  } else {
    //符合条件回调true
    callback(true);
  }
}, function(results){
    // results为符合过滤后的数据
    console.log(results);
});

filter也是一个并行执行的方法,如需要顺序执行请使用filterSeries方法。其它filter相关方法请参考Async API


4. reduce(arr, memo, iterator(memo, item, callback(err, reduction)), callback(err, result))

按初始值对集合中的数据进行处理后得到一个唯一的结果。reduce是一个按顺序对集合中数据进行运算的操作,效率较低,运算量较大时应该避免使用。

参数

arr:要执行运算的数组。
memo:执行运算的初始值。
iterator(memo, item, callback):对arr中的对象执行运算的方法。本次运算执行完成后执行callback(err, reduction)回调,本次回调的reduction将做为下次运算的初始memo。
callback(err, result):最终回调方法。result为最终的运算结果。

示例

async.reduce([1,2,3], 0, function(memo, item, callback){
    // 执行异步运算
    process.nextTick(function(){
        callback(null, memo + item)
    });
}, function(err, result){
    //reduce计算完成后最终计算结果result等于6
    console.log(result)
});

reduce方法是将结果集从左至右进行运算,如果需要从右至左进行运算请使用reduceRight方法。

async中集合操作的方法还有很多,更多集合操作方法可参考其github文档:Async.js