前言
針對JS的異步機制,JS社區給出了很多不同的解決方案,Async庫便是其中一種,可能也是對於控制異步操作最全面的資源。因爲該庫提供了70個函數,幾乎想所有的運用場景都考慮在內。
parallel
函數是平行執行
'use strict';
var async = require('async');
var some = 'hello';
//watchfall 最後一個參數是回調,前面的是參數
var first = function (cb) {
console.log('i am first!');
some = some + ' www ';
//cb(new Error('i am error'), 10);
cb(null, 10);
};
var second = function (cb, data) {
console.log('i am second,data:', data);
some = some + ' world';
cb(null, 1000);
};
var end = function (err, data, data1) {
console.log('end err:', err);
console.log('end data:', data);
console.log('end data1:', data1);
}
async.parallel([first, second], end);
/*
async.parallel({ first, second }, end);
*/
console.log('end.....', some);
series
函數順序執行
'use strict';
var async = require('async');
var some = 'hello';
//watchfall 最後一個參數是回調,前面的是參數
var first = function (cb) {
console.log('i am first!');
some = some + ' www ';
//cb(new Error('i am error'), 10);
cb(null, 10);
};
var second = function (cb, data) {
console.log('i am second,data:', data);
some = some + ' world';
cb(null, 1000);
};
var end = function (err, data, data1) {
console.log('end err:', err);
console.log('end data:', data);
console.log('end data1:', data1);
}
async.series([first, second], end);
console.log('-----------------------------------------');
console.log('-----------------------------------------');
async.series({ first, second }, end);
console.log('end.....', some);
watchfall
waterfall(tasks, [callback])
(多個函數依次執行,且前一個的輸出爲後一個的輸入)按順序依次執行多個函數。每一個函數產生的值,都將傳給下一個函數。如果中途出錯,後面的函數將不會被執行。錯誤信息以及之前產生的結果,將傳給waterfall最終的callback。
對於學過了js回調機制的小夥伴,waterfall是比較容易理解的,個人的理解就是,waterfall中傳入的函數數組tasks中,後一個函數爲前一個函數的回調,使用cb(null,args),這樣的形式調用下一個函數,如果出現異常,則直接使用cb(new Error(“錯誤的信息”))這樣的方式來捕捉異常,並調用最終的回調函數來處理,在這種情況下,出現異常的函數後面那些函數,將不再繼續執行,測試代碼如下:
var async = require('async');
var a = 10;
async.waterfall([
function(cb) {
console.log("getb")
setTimeout(function() {
if (a == 0) {
cb(new Error("a不能爲0"));
} else {
var b = 1 / a;
cb(null, b); //在這裏通過回調函數把b傳給下一個函數,記得一定要加上null,才能調用數組中得下一個函數,否則,會直接調用最終的回調函數,然後結束函數,則後面的函數將不再執行
//如果這裏寫成cb(b);
//結果會變成:
/**
*getb
*0.1
**/
}
}, 1000);
},
function(b, cb) {
setTimeout(function() {
console.log("getc")
var c = b + 1;
cb(null,c);
}, 1000);
}
], function(err, result) {
if (err) {
console.log(err);
} else {
console.log('c:' + result)
}
});
當a = 0時,會直接拋出錯誤,輸出如下:
getb
Error: a不能爲0
先執行了第一個函數,在第一個函數中拋出異常之後,直接執行最終的回調函數,並沒有接着執行第二個函數。
a = 10 時,輸出如下:
getb
getc
1.1
先執行了第一個函數,然後把第一個函數算出的b傳給了第二個函數,再次算出第二個函數中得C,傳給最終的結果result。
https://github.com/caolan/async/blob/v1.5.2/README.md#waterfall
map,mapLimit
map(coll, iteratee, callbackopt)
mapLimit(coll, limit, iteratee, callbackopt)
whilst(test, iteratee, callbackopt)
Repeatedly call iteratee, while test returns true. Calls callback when stopped, or an error occurs.
var count = 0;
async.whilst(
function test(cb) { cb(null, count < 5); },
function iter(callback) {
count++;
setTimeout(function() {
callback(null, count);
}, 1000);
},
function (err, n) {
// 5 seconds have passed, n = 5
}
);
之前關於test部分的寫法是:
function () { return count < 5; }, 這樣寫,導致後面iter函數並不會執行,直接跳過這個函數。在這個函數栽過跟頭。