我的博客: http://zhangsunyucong.topnode
這篇文章主要講兩個內容,一是,初步認識Promise,二是,Async模塊和Async/Await的使用git
Promise表示一個異步操做的最終結果。一個Promise對象有一個then方法,then方法中返回一個Promise。github
- promise是一個包含了兼容promise規範then方法的對象或函數,
Promise有三種狀態:pending, fulfilled 或 rejected。pending是等待執行狀態,fulfilled是成功執行狀態,rejected是失敗執行狀態。npm
Promise只能從pending到fulfilled或者從pending到rejected狀態,當狀態發生改變時,promise.then(onFulfilled, onRejected)方法將被調用。Promise可使用resolve或者reject將value或者reason做爲下一個Promise的第一個回調參數。segmentfault
來個簡單的Promise基本用法:數組
var promise = new Promise(function(resolve, reject){
//do something
if(success){
resolve(value);
} else {
reject(value);
}
});
promise.then(function(value){
//成功時調用
}, function(value){
//失敗時調用
});
複製代碼
上面的代碼只是表示Promise用法的流程.promise
使用Promise/A+規範實現如下幾個功能bash
- 上一步的結果能夠做爲下一步的參數
Promise的具體知識,能夠參考這裏異步
下面介紹Async模塊和ES7的Async/Await的使用async
Async模塊的github地址:github.com/caolan/asyn…
配置好node的環境後(具體過程,本身百度),安裝Async模塊
npm install --save async
Async模塊提供了不少關於集合,流程控制,工具方法,這裏只體驗幾個常見的流程控制方法:series,parallel,waterfall,auto。其餘方法的用法,能夠查看官方文檔:文檔地址
series(tasks, callback)
tasks能夠是數組或者對象
series是串行執行tasks中的任務,若是有一個任務執行返回了錯誤信息,則再也不繼續執行後面未執行的任務,並將結果以數組或者對象的形式傳給callback。具體結果的格式由你定義tasks時使用的是數組仍是對象。
async.series([
function (callback) {
setTimeout(function () {
console.log("one");
callback(null, 'one');
}, 300);
},
function (callback) {
setTimeout(function () {
console.log("two");
callback(null, 'two');
}, 200);
},
function (callback) {
setTimeout(function () {
console.log("three");
callback(null, 'three');
}, 100);
}
], function (err, results) {
console.log(err);
console.log(results);
});
複製代碼
運行結果:
one two three null [ 'one', 'two', 'three' ]
當tasks是對象:
async.series({
one: function (callback) {
setTimeout(function () {
console.log("one");
callback(null, 'one');
}, 300);
},
two: function (callback) {
setTimeout(function () {
console.log("two");
callback(null, 'two');
}, 200);
},
three: function (callback) {
setTimeout(function () {
console.log("three");
callback(null, 'three');
}, 100);
}
}, function (err, results) {
if(err) {
console.log("異常結束" + '結果爲:' + results);
return;
}
console.log(results);
});
複製代碼
運行結果:
one two three { one: 'one', two: 'two', three: 'three' }
上面代碼中,從上到下的函數開始執行時間是逐漸減少的,而運行結果的輸出順序是one,two,three,說明series是串行執行任務的。
將第二個任務的代碼改成如下的樣子:
function (callback) {
console.log("two");
setTimeout(function () {
callback("errMsg", 'two');
}, 200);
}
複製代碼
運行的結果爲:
one two errMsg [ 'one', 'two' ]
能夠看到,當第二個任務返回了錯誤信息,則不會再繼續執行後面未執行的任務
parallel(tasks, callback)
tasks能夠是一個數組或者對象
parallel是並行執行多個任務,若是有一個任務執行返回了一個錯誤信息,則再也不繼續執行後面未執行的任務,並將結果以數組或者對象的形式傳給callback。
async.parallel([
function (callback) {
setTimeout(function() {
console.log('one');
callback(null, 'one');
}, 500);
},
function (callback) {
setTimeout(function() {
console.log('two');
callback(null, 'two');
}, 200);
},
function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 100);
}
], function (err, results) {
console.log(err);
console.log(results);
});
複製代碼
運行結果爲:
three two one null [ 'one', 'two', 'three' ]
結果中的輸出順序是three,two,one,說明parallel是並行執行任務的。
一樣,將第二個任務的代碼改成:(數組定義tasks)
function (callback) {
setTimeout(function() {
console.log('two');
callback("errMsg", 'two');
}, 200);
},
複製代碼
運行的結果爲:
three two errMsg [ <1 empty item>, 'two', 'three' ] one
將第二個任務代碼改成:(數組定義tasks)
function (callback) {
setTimeout(function() {
console.log('two');
callback("errMsg", 'two');
}, 200);
},
複製代碼
將第三個任務代碼改成:(數組定義tasks)
function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 200);
}
複製代碼
也就是,第三個的開始執行時間改爲和出現錯誤信息的第二個任務的時間同樣。
運行的結果爲:
two errMsg [ <1 empty item>, 'two' ] three one
從結果中能夠看出,當前面執行的未完成的任務會佔一個位置,然後面未完成的任務不會佔數組的位置。
parallelLimit(tasks, limit, callback)
parallelLimit和parallel差很少,區別是它能夠指定同時並行執行任務的最大數量。
async.parallelLimit({
one: function (callback) {
setTimeout(function() {
console.log('one');
callback(null, 'one');
}, 200);
},
two: function (callback) {
setTimeout(function() {
console.log('two');
callback(error, 'two');
}, 200);
},
three: function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 100);
}
}, 2, function (err, results) {
console.log(err);
console.log(results);
});
複製代碼
運行的結果爲:
one two errMsg { one: 'one', two: 'two' } three
若是是tasks是數組時,運行的結果是:
two errMsg [ <1 empty item>, 'two' ] one
因爲同時並行執行任務的最大數量是2,因爲第二個任務產生錯誤信息,第三個任務還沒開始執行。另外若是要取最後回調結果中的值,對象定義tasks可能會更好。
waterfall(tasks, callback)
tasks只能是數組類型
waterfall會串行執行tasks中的任務,前一個任務的結果能夠做爲下一個任務的參數。
async.waterfall([
function (callback) {
console.log("one");
setTimeout(function() {
callback(null, 'one', 'two');
}, 200);
},
function (arg1, arg2, callback) {
console.log("two" + '參數:' + "arg1是" + arg1 + "arg2是" + arg2);
setTimeout(function() {
callback(null, 'three');
}, 200);
},
function (arg3, callback) {
console.log("three" + '參數:' + "arg3是" + arg3);
setTimeout(function() {
callback(null, 'done', 'done1');
}, 200);
}
], function (err, results) {
if(err) {
console.log("異常結束" + '結果爲:' + results);
return;
}
console.log(results);
});
複製代碼
運行的結果是:
one two參數:arg1是onearg2是two three參數:arg3是three done
輸出的結果的順序是one,two, three,是串行執行的。前一個任務的結果能夠做爲下一個任務的參數。
注意一下,代碼中控制檯輸出的one,two,three代碼是移到了定時器的外面。
auto(tasks, concurrencyopt, callback)
auto能夠串行和並行執行任務,能夠定義任務之間的依賴關係。沒有依賴關係的任務會盡量快的開始並行執行,串行是因爲任務的依賴關係而實現的。concurrencyopt指定的是並行執行任務的最大數量。tasks只能是對象類型。
async.auto({
task1: function(callback) {
setTimeout(function() {
console.log('task1');
callback(null, 'data', 'data1');
}, 200);
},
task2: function(callback) {
setTimeout(function () {
console.log('task2');
callback(null, 'data2');
}, 100)
},
task3: ['task1', 'task2', function(results, callback) {
console.log('task3', JSON.stringify(results));
setTimeout(function () {
console.log('task3');
callback(null, 'data3');
}, 200);
}],
task4: ['task3', function(results, callback) {
console.log('task4', JSON.stringify(results));
setTimeout(function () {
console.log('task4');
callback(null, {'task2':results.task2, 'task4':'data4'});
}, 100);
}]
}, function(err, results) {
console.log('err = ', err);
console.log('results = ', results);
});
複製代碼
運行的結果是:
task2 task1 task3 {"task2":"data2","task1":["data","data1"]} task3 task4 {"task2":"data2","task1":["data","data1"],"task3":"data3"} task4 err = null results = { task2: 'data2', task1: [ 'data', 'data1' ], task3: 'data3', task4: { task2: 'data2', task4: 'data4' } }
task1和task2是不依賴於任何其餘任務的,它們會盡量的開始,並且因爲它們是並行執行的,task2的開始時間較短,因此task2比task1先開始。task3依賴於task1和task2,因此task3等到task1和task2執行完畢後再執行。task4依賴task3,因此task4要等到task3執行完畢後再執行。
主要看它們的用法
var task1 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("result");
}, 1000);
});
};
var excTask1 = async function () {
console.log("start");
console.log(await task1());
console.log("end");
};
function awaitDemo() {
excTask1();
}
複製代碼
連續點擊運行四次,運行的結果爲:
start start start start result end result end result end result end
async表明是一個async函數,await只能用在async函數中,await等待一個Promise的返回,直到Promise返回了纔會繼續執行await後面的代碼。這裏的Promise利用setTimeout模擬異步任務。
從輸出結果中能夠看出,每次執行都是到await時,就中止等待Promise的返回,後再繼續執行await後面的代碼。