Node.js 中使用 Promise Q
假設我們今天要執行一項工作task 3,但執行task 3之前要先依序完成工作task 2與task 1。
如果沒有使用promise,而用callback的方式完成,程式碼大概會是這樣...
task1(function (value1) {
task2(value1, function(value2) {
task3(value2, function(value3) {
//do something with value3...
});
});
});
要做(依賴)的事情愈多,深度就愈深,完全就是callback hell了。
使用Promise
承上,若使用promise,只要等到目前的工作(task 1)完成,回傳一個訊息告知下一個工作(task 2)可以開始動工,就解決這個callback hell的問題了。
var Q = require('q');,
deferred = Q.defer();
function task1(value1) {
var response = "Complete task with " + value1;
deferred.resolve(response);
return deferred.promise;
};
function task2(value2) {
console.log(value2);
};
task1('Hello World').then(function(success) {
task2(success);
},function(error){
console.log(error);
},function(progress){
console.log(progress);
});
注意,回傳的promise有三種狀態:
- 回傳成功:
deferred.resolve('resolve')
- 回傳失敗:
deferred.reject('reject')
- 回傳處理中:
deferred.notify('in progress')
為了舉例方便,範例只呈現了回傳成功的狀態。
結果
Complete task with Hello World
改寫前面依序執行三個工作(task 1、task 2與task 3)的callback hell。
function task1(value){
var deferred = Q.defer(),
response = "Complete task" + value + " with Hello World" + value;
deferred.resolve(response);
return deferred.promise;
};
function task2(value){
var deferred = Q.defer(),
response = "Complete task" + value + " with Hello World" + value;
deferred.resolve(response);
return deferred.promise;
};
function task3(value){
var deferred = Q.defer(),
response = "Complete task" + value + " with Hello World" + value;
deferred.resolve(response);
return deferred.promise;
};
var promise1 = task1('1'),
promise2,
promise3;
promise2 = promise1.then(function(res) {
console.log(res);
return task2('2');
});
promise3 = promise2.then(function(res) {
console.log(res);
return task3('3');
});
promise3.then(function(res) {
console.log(res);
});
promise2 = promise1.then(function(res) {
console.log(res);
return task2('2');
});
簡化
由於return的值都是promise,因此可以簡化成以下的樣子。
task1('1')
.then(function(res) {
console.log(res);
return task2('2');
})
.then(function(res) {
console.log(res);
return task3('3');
})
.done(function(res){
console.log(res);
});
結果
Complete task1 with Hello World1
Complete task2 with Hello World2
Complete task3 with Hello World3
Q.all[]
但若要等待多個工作呢?例如:等待task 1與task 2(任意順序)完成後,再繼續完成task 3。
var Q = require('q');
function task1(value1){
var response = "Complete task with " + value1,
deferred = Q.defer();
deferred.resolve(response);
return deferred.promise;
};
function task2(value2){
var response = "Complete task with " + value2,
deferred = Q.defer();
deferred.resolve(response);
return deferred.promise;
};
function task3(result1, result2) {
console.log(result1);
console.log(result2);
};
var value1 = "Hello",
value2 = "World",
promise = Q.all([task1(value1), task2(value2)]);
promise.then(function(results){
task3(results[0], results[1]);
});
將taks 1和task 2放到 Q.all[]
中,當task 1或task 2完成時,會回傳promise。當task 1與task 2都回傳promise時,就會經由 promise.then()
執行接下來的工作,也就是task 3。
結果
Complete task with Hello
Complete task with World
References
- kriskowal/q
- Promise - Q函式庫
- Javascript - Promise, generator, async與ES6
- 在Node.js中使用promise擺脫回調金字塔
- 在Node.js 中用Q 實現Promise – Callbacks之外的另一種選擇
由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-Node.js 中使用 Promise Q。
留言