Async提供了不少針對集合的函數,能夠簡化咱們對集合進行異步操做時的步驟。以下:node
forEach:對集合中每一個元素進行異步操做git
map:對集合中的每一個元素經過異步操做獲得另外一個值,獲得新的集合github
filter:對集合中元素使用異步操做進行篩選,獲得符合條件的集合數組
reject:與filter類似,只是判斷條件時正好相反,獲得剩下的元素的集合異步
reduce:使用一個初始值同集合中每個元素進行異步操做,最後獲得一個惟一的結果async
detect:獲得集合中知足條件的第一個數據函數
sortBy:對集合中的數據進行異步操做,再根據值從小到大排序性能
some/any:集合中是否有至少一個元素知足條件prototype
every/all:集合中是否每一個元素都知足條件對象
concat:對集合中的元素進行異步操做,將結果集合併成一個數組
下面一一解釋:
若是想對同一個集合中的全部元素都執行同一個異步操做,能夠利用forEach函數。注意該函數將重點放在「執行過程」上,忽略運行後產生的數據。若是須要結果,可以使用map函數。
根據執行的方式不一樣,forEach提供了三個版本:
集合中全部元素並行執行
一個一個順序執行
分批執行,同一批內並行,批與批之間按順序
首先看並行執行的例子,它比較簡單,只是打印出傳入的元素內容:
var arr = [{name:'Jack', delay: 200},
{name:'Mike', delay: 100},
{name:'Freewind', delay: 300}];
async.forEach(arr, function(item, callback) {
log(’1.1 enter: ‘ + item.name);
setTimeout(function(){
log(’1.1 handle: ‘ + item.name);
callback();
}, item.delay);
}, function(err) {
log(’1.1 err: ‘ + err);
});
它將打出以下結果:
42.244> 1.1 enter: Jack
42.245> 1.1 enter: Mike
42.245> 1.1 enter: Freewind
42.350> 1.1 handle: Mike
42.445> 1.1 handle: Jack
42.554> 1.1 handle: Freewind
42.554> 1.1 err: undefined
最前面的數據是當前的時間值(秒.毫秒),從中能夠看到各異步操做是並行執行的。
若是想同步執行,須要使用forEachSeries函數,它與forEach的用法如出一轍,只是執行時是一個一個來的。這裏就不給例子了。
當集合中元素不少,既不想一次所有並行操做,又不想一個一個按順序來,可使用forEachLimit函數。它能夠設定一批處理幾個,每一批內並行執行,批與批之間順序執行。
async.forEachLimit(arr, 2, function(item, callback) {
log(’1.5 enter: ‘ + item.name);
setTimeout(function(){
log(’1.5 handle: ‘ + item.name);
callback(null, item.name);
}, item.delay);
}, function(err) {
log(’1.5 err: ‘ + err);
});
打印結果以下:
42.247> 1.5 enter: Jack
42.248> 1.5 enter: Mike
42.351> 1.5 handle: Mike
42.352> 1.5 enter: Freewind
42.461> 1.5 handle: Jack
42.664> 1.5 handle: Freewind
42.664> 1.5 err: undefined
能夠看到前兩個是同時開始的,而第三個是等前兩個都完成之後纔開始的。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/forEach.js
map的重點是轉換,即把集合中的元素經過異步操做轉爲另外一個對象,最後能夠獲得轉換後的對象數組。它也提供了並行與順序執行兩種方式。
這裏給一個示例,給集合中的每一個元素以異步方式增長!!!:
var arr = [{name:'Jack', delay:200}, {name:'Mike', delay: 100}, {name:'Freewind', delay:300}, {name:'Test', delay: 50}];
async.map(arr, function(item, callback) {
log(’1.1 enter: ‘ + item.name);
setTimeout(function() {
log(’1.1 handle: ‘ + item.name);
callback(null, item.name+’!!!’);
}, item.delay);
}, function(err,results) {
log(’1.1 err: ‘, err);
log(’1.1 results: ‘, results);
});
打印結果以下:
54.569> 1.1 enter: Jack
54.569> 1.1 enter: Mike
54.569> 1.1 enter: Freewind
54.569> 1.1 enter: Test
54.629> 1.1 handle: Test
54.679> 1.1 handle: Mike
54.789> 1.1 handle: Jack
54.879> 1.1 handle: Freewind
54.879> 1.1 err:
54.879> 1.1 results: [ 'Jack!!!', 'Mike!!!', 'Freewind!!!', 'Test!!!' ]
能夠看到,對各元素的操做是並行的,結果會彙總在一塊兒交給最後的回調。
若是想順序執行,可以使用mapSeries,它與map的用法如出一轍。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/map.js
使用異步操做對集合中的元素進行篩選。須要注意的是,iterator的callback只有一個參數,只能接收true或false。
對於出錯,該函數沒有作出任何處理,直接由nodejs拋出。因此須要注意對Error的處理。
提供了並行與順序執行兩種方式。
並行示例,找到全部>=3的元素:
async.filter([1,2,3,4,5], function(item, callback) {
log(’1.1 enter: ‘ + item);
setTimeout(function() {
log(’1.1 test: ‘ + item);
callback(item>=3);
}, 200);
}, function(results) {
log(’1.1 results: ‘, results);
});
打印結果以下:
16.739> 1.1 enter: 1
16.749> 1.1 enter: 2
16.749> 1.1 enter: 3
16.749> 1.1 enter: 4
16.749> 1.1 enter: 5
16.749> 1.3 enter: 1
16.949> 1.1 test: 1
16.949> 1.1 test: 2
16.949> 1.1 test: 3
16.949> 1.1 test: 4
16.949> 1.1 test: 5
16.949> 1.1 results: [ 3, 4, 5 ]
可見找到了知足條件的全部元素。
若是須要順序執行,可使用filterSeries函數,它的用法與filter同樣。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/filter_reject.js
reject與filter類似,只是行爲正好相反。當條件爲true時,它將丟棄相應的元素。它也提供了並行與順序執行兩種方式。
並行示例,去掉全部>=3的元素:
async.reject([1,2,3,4,5], function(item, callback) {
log(’1.4 enter: ‘ + item);
setTimeout(function() {
log(’1.4 test: ‘ + item);
callback(item>=3);
}, 200);
}, function(results) {
log(’1.4 results: ‘, results);
});
打印結果以下:
31.359> 1.4 enter: 1
31.359> 1.4 enter: 2
31.359> 1.4 enter: 3
31.359> 1.4 enter: 4
31.359> 1.4 enter: 5
31.559> 1.4 test: 1
31.559> 1.4 test: 2
31.559> 1.4 test: 3
31.559> 1.4 test: 4
31.559> 1.4 test: 5
31.569> 1.4 results: [ 1, 2 ]
若是想順序執行,可以使用rejectSeries,它與reject用法同樣。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/filter_reject.js
Reduce可讓咱們給定一個初始值,用它與集合中的每個元素作運算,最後獲得一個值。reduce從左向右來遍歷元素,若是想從右向左,可以使用reduceRight。
這裏給個例子,計算出100與某個集合中全部數之和:
var arr = [1,3,5];
async.reduce(arr, 100, function(memo, item, callback) {
log(’1.1 enter: ‘ + memo +’, ‘ + item);
setTimeout(function() {
callback(null, memo+item);
}, 100);
},function(err, result) {
log(’1.1 err: ‘, err);
log(’1.1 result: ‘, result);
});
將打印出結果:
28.789> 1.1 enter: 100, 1
28.889> 1.1 enter: 101, 3
28.999> 1.1 enter: 104, 5
29.109> 1.1 err:
29.109> 1.1 result: 109
須要注意的是,async中的reduce,不是並行操做,而是對元素一個個順序操做,因此當元素比較多時,性能會比較弱。若是想提升性能,可以使用async.map函數,先並行獲得集合中每一個元素被處理以後的值,而後再使用Array.prototype.reduce函數處理,性能會快不少。
對於這個例子:
async.reduce(arr, 100, function(memo,item,callback) {
log(’1.4 enter: ‘+memo+’,'+item);
t.inc(item, function(err,n) {
log(’1.4 handle: ‘,n);
callback(null, memo+n);
});
}, function(err,result) {
log(’1.4 err: ‘, err);
log(’1.4 result: ‘, result);
});
它總耗時爲0.62秒。若是換成map+array.reduce:
async.map(arr, function(item, callback) {
log(’1.5 enter: ‘, item);
t.inc(item, function(err,n){
log(’1.5 handle: ‘, n);
callback(null,n);
});
},function(err, results) {
log(’1.5 err: ‘, err);
log(’1.5 results: ‘, results);
var sum = results.reduce(function(memo, item) {
return memo + item;
}, 100);
log(’1.5 sum: ‘, sum);
});
耗時爲0.21秒。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/reduce.js
用於取得集合中知足條件的第一個元素。它分爲並行與順序執行兩種方式,分別對應函數detect和detectSeries。
並行示例,找到一個奇數:
var arr = [{value:1,delay:500},
{value:2,delay:200},
{value:3,delay:300}];
async.detect(arr, function(item,callback){
log(’1.1 enter: ‘, item.value);
setTimeout(function() {log(’1.1 handle: ‘, item.value);
callback(n%2===1);
}, item.delay);
}, function(result) {
log(’1.1 result: ‘, result);
});
結果以下:
09.928> 1.1 enter: 1
09.928> 1.1 enter: 2
09.928> 1.1 enter: 3
10.138> 1.1 handle: 2
10.228> 1.1 handle: 3
10.228> 1.1 result: { value: 3, delay: 300 }
10.438> 1.1 handle: 1
10.438> 1.1 handle: 1
可見獲得了最早執行完的那個奇數3.
更多詳細示例:https://github.com/freewind/async_demo/blob/master/detect.js
對集合內的元素進行排序,依據每一個元素進行某異步操做後產生的值,從小到大排序。
示例:
var arr = [3,6,1];
async.sortBy(arr, function(item, callback) {
setTimeout(function() {
callback(null,item);
}, 200);
}, function(err,results) {
log(’1.1 err: ‘, err);
log(’1.1 results: ‘, results);
});
打印結果以下:
26.562> 1.1 err: null
26.562> 1.1 results: [ 1, 3, 6 ]
能夠看到集合中的數據從小到大排好了序。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/sortBy.js
當集合中是否有至少一個元素知足條件時,最終callback獲得的值爲true,不然爲false。它有一個別名叫any。
判斷集合中是否有元素小於等於3:
async.some([1,2,3,6], function(item,callback){
log(’1.1 enter: ‘,item);
setTimeout(function(){
log(’1.1 handle: ‘,item);
callback(item<=3);
},100);
}, function(result) {
log(’1.1 result: ‘, result);
});
打印結果以下:
36.165> 1.1 enter: 1
36.165> 1.1 enter: 2
36.165> 1.1 enter: 3
36.165> 1.1 enter: 6
36.275> 1.1 handle: 1
36.275> 1.1 result: true
36.275> 1.1 handle: 2
36.275> 1.1 handle: 3
36.275> 1.1 handle: 6
可見的確獲得告終果true。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/some.js
若是集合裏每個元素都知足條件,則傳給最終回調的result爲true,不然爲false
在下面的示例中,由於集合中每一個元素都<=10,因此最終結果爲true
async.every(arr, function(item,callback){
log(’1.1 enter: ‘,item);
setTimeout(function(){
log(’1.1 handle: ‘,item);
callback(item<=10);
},100);
}, function(result) {
log(’1.1 result: ‘, result);
});
打印以下:
32.113> 1.1 enter: 1
32.123> 1.1 enter: 2
32.123> 1.1 enter: 3
32.123> 1.1 enter: 6
32.233> 1.1 handle: 1
32.233> 1.1 handle: 2
32.233> 1.1 handle: 3
32.233> 1.1 handle: 6
32.233> 1.1 result: true
可見最終結果爲true
更多詳細示例:https://github.com/freewind/async_demo/blob/master/every.js
將合併多個異步操做的結果合併爲一個數組。
在下面的示例中,將集合中的每個元素都加倍:
async.concat(['aa','bb'], function(item,callback) {
setTimeout(function() {
callback(null, [item, item]);
}, 100);
}, function(err, values) {
log(’1.1 err: ‘, err);
log(’1.1 values: ‘, values);
});
打印以下:
13.539> 1.1 err:
13.639> 1.1 values: [ 'aa', 'aa', 'bb', 'bb' ]
打印出來的是通過合併後的數組。
更多詳細示例:https://github.com/freewind/async_demo/blob/master/concat.js