node使用promise替代回調(diào)函數(shù)
在學(xué)習(xí) Node.js 過(guò)程中接觸到了如何使用 async 來(lái)控制并發(fā)(使用 async 控制并發(fā))
async 的本質(zhì)是一個(gè)流程控制。其實(shí)在異步編程中,還有一個(gè)更為經(jīng)典的模型,叫做 Promise/Deferred 模型(當(dāng)然還有更多相關(guān)解決方法,比如 eventproxy,co 等,到時(shí)候遇到在挖坑)
首先,我們思考一個(gè)典型的異步編程模型,考慮這樣一個(gè)題目:讀取一個(gè)文件,在控制臺(tái)輸出這個(gè)文件內(nèi)容
var fs = require('fs');
fs.readFile('1.txt', 'utf8', function (err, data) {
console.log(data);
});
看起來(lái)很簡(jiǎn)單,再進(jìn)一步: 讀取兩個(gè)文件,在控制臺(tái)輸出這兩個(gè)文件內(nèi)容
var fs = require('fs');
fs.readFile('1.txt', 'utf8', function (err, data) {
console.log(data);
fs.readFile('2.txt', 'utf8', function (err, data) {
console.log(data);
});
});
要是讀取更多的文件呢
var fs = require('fs');
fs.readFile('1.txt', 'utf8', function (err, data) {
fs.readFile('2.txt', 'utf8', function (err, data) {
fs.readFile('3.txt', 'utf8', function (err, data) {
fs.readFile('4.txt', 'utf8', function (err, data) {
// ...
});
});
});
});
這就是傳說(shuō)中的 callback hell,可以使用 async 來(lái)改善這段代碼,但是在本例中我們要用 promise/defer 來(lái)改善它
promise 基本概念
首先它是一個(gè)對(duì)象,它和 javascript 普通的對(duì)象沒(méi)什么區(qū)別,同時(shí),它也是一種規(guī)范,跟異步操作約定了統(tǒng)一的接口,表示一個(gè)異步操作的最終結(jié)果,以同步的方式來(lái)寫代碼,執(zhí)行的操作是異步的,但又保證程序執(zhí)行的順序是同步的
1. promise 只有三種狀態(tài),未完成,完成 (fulfilled) 和失敗 (rejected)
2. promise 的狀態(tài)可以由未完成轉(zhuǎn)換成完成,或者未完成轉(zhuǎn)換成失敗
3. promise 的狀態(tài)轉(zhuǎn)換只發(fā)生一次
promise 有一個(gè) then 方法,then 方法可以接受 3 個(gè)函數(shù)作為參數(shù)。前兩個(gè)函數(shù)對(duì)應(yīng) promise 的兩種狀態(tài) fulfilled, rejected 的回調(diào)函數(shù)。第三個(gè)函數(shù)用于處理進(jìn)度信息
為了理解它,一些重要原理必須記牢:.then() 總是返回一個(gè)新的 promise,如下面代碼:
var promise = readFile() var promise2 = promise.then(readAnotherFile, console.error)
這里 then 的參數(shù) readAnotherFile, console.error 是代表異步操作成功后的動(dòng)作 onFulfilled 或失敗后的動(dòng)作 OnRejected,也就是說(shuō),讀取文件成功后執(zhí)行 readAnotherFile 函數(shù),否則失敗打印記錄錯(cuò)誤。這種實(shí)現(xiàn)是兩個(gè)中只有一種可能
也可以理解為:
promiseSomething().then(function (fulfilled) {
// 當(dāng) promise 狀態(tài)變成 fulfilled 時(shí),調(diào)用此函數(shù)
}, function (rejected) {
// 當(dāng) promise 狀態(tài)變成 rejected 時(shí),調(diào)用此函數(shù)
}, function (progress) {
// 當(dāng)返回進(jìn)度信息時(shí),調(diào)用此函數(shù)
});
Promise 法則有兩部分必須分離:
1. then() 總是返回一個(gè)新的 promise,每次你調(diào)用它,它不管回調(diào)做什么,因?yàn)?.then() 在回調(diào)被調(diào)用之前已經(jīng)給了你一個(gè)承諾 promise,回調(diào)的行為只影響承諾 promise 的實(shí)施,如果回調(diào)返回一個(gè)值,那么 promise 將使用那個(gè)值,如果這個(gè)值是一個(gè) promise,返回這個(gè) promise 實(shí)施后的值給這個(gè)值,如果回調(diào)拋出錯(cuò)誤,promise 將拒絕錯(cuò)誤
2. 被 .then() 返回的 promise 是一個(gè)新的 promise ,它不同于那些 .then() 被調(diào)用的 promise,promise 長(zhǎng)長(zhǎng)的鏈條有時(shí)會(huì)好些隱藏這個(gè)事實(shí),不管如何,每次 .then() 調(diào)用都會(huì)產(chǎn)生一個(gè)新的 promise,這里必須注意的是你真正需要考慮的是你最后調(diào)用 .then() 可能代表失敗,那么如果你不捕獲這種失敗,那么容易導(dǎo)致你的錯(cuò)誤 exception 消失
來(lái)看一個(gè)利用 q 來(lái)處理這種問(wèn)題的簡(jiǎn)單例子:
var Q = require('q');
var defer = Q.defer();
/**
* 獲取初始 promise
* @private
*/
function getInitialPromise() {
return defer.promise;
}
/**
* 為 promise 設(shè)置三種狀態(tài)的回調(diào)函數(shù)
*/
getInitialPromise().then(function (success) {
console.log(success);
}, function (error) {
console.log(error);
}, function (progress) {
console.log(progress);
});
defer.notify('in progress'); // 控制臺(tái)打印 in progress
defer.resolve('resolve'); // 控制臺(tái)打印 resolve
defer.reject('reject'); // 沒(méi)有輸出。promise 的狀態(tài)只能改變一次
promise 的傳遞
then 方法會(huì)返回一個(gè) promise,在下面這個(gè)例子中,我們用 outputPromise 指向 then 返回的 promise。
var outputPromise = getInputPromise().then(function (fulfilled) {
}, function (rejected) {
});
現(xiàn)在 outputPromise 就變成了受 function(fulfilled) 或者 function(rejected) 控制狀態(tài)的 promise 了。直白的意思就是:當(dāng) function(fulfilled) 或者 function(rejected) 返回一個(gè)值,比如一個(gè)字符串,數(shù)組,對(duì)象等等,那么 outputPromise 的狀態(tài)就會(huì)變成 fulfilled。
在下面這個(gè)例子中,我們可以看到,當(dāng)我們把 inputPromise 的狀態(tài)通過(guò) defer.resovle() 變成 fulfilled 時(shí),控制臺(tái)輸出 fulfilled.
當(dāng)我們把 inputPromise 的狀態(tài)通過(guò) defer.reject() 變成 rejected,控制臺(tái)輸出 rejected
var Q = require('q');
var defer = Q.defer();
/**
* 通過(guò) defer 獲得 promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled)
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected 時(shí),調(diào)用 function(rejected)
* 將 then 返回的 promise 賦給 outputPromise
* function(fulfilled) 和 function(rejected) 通過(guò)返回字符串將 outputPromise 的狀態(tài)由
* 未完成改變?yōu)?fulfilled
* @private
*/
var outputPromise = getInputPromise().then(function (fulfilled) {
return 'fulfilled';
}, function (rejected) {
return 'rejected';
});
/**
* 當(dāng) outputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled),控制臺(tái)打印 'fulfilled: fulfilled'。
* 當(dāng) outputPromise 狀態(tài)由未完成變成 rejected, 調(diào)用 function(rejected), 控制臺(tái)打印 'rejected: rejected'。
*/
outputPromise.then(function (fulfilled) {
console.log('fulfilled: ' + fulfilled);
}, function (rejected) {
console.log('rejected: ' + rejected);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
defer.reject(); // 輸出 fulfilled: rejected
/**
* 將 inputPromise 的狀態(tài)由未完成變成 fulfilled
*/
//defer.resolve(); // 輸出 fulfilled: fulfilled
當(dāng) function(fulfilled) 或者 function(rejected) 拋出異常時(shí),那么 outputPromise 的狀態(tài)就會(huì)變成 rejected
var Q = require('q');
var fs = require('fs');
var defer = Q.defer();
/**
* 通過(guò) defer 獲得 promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled)
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected 時(shí),調(diào)用 function(rejected)
* 將 then 返回的 promise 賦給 outputPromise
* function(fulfilled) 和 function(rejected) 通過(guò)拋出異常將 outputPromise 的狀態(tài)由
* 未完成改變?yōu)?reject
* @private
*/
var outputPromise = getInputPromise().then(function (fulfilled) {
throw new Error('fulfilled');
}, function (rejected) {
throw new Error('rejected');
});
/**
* 當(dāng) outputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled)。
* 當(dāng) outputPromise 狀態(tài)由未完成變成 rejected, 調(diào)用 function(rejected)。
*/
outputPromise.then(function (fulfilled) {
console.log('fulfilled: ' + fulfilled);
}, function (rejected) {
console.log('rejected: ' + rejected);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
defer.reject(); // 控制臺(tái)打印 rejected [Error:rejected]
/**
* 將 inputPromise 的狀態(tài)由未完成變成 fulfilled
*/
//defer.resolve(); // 控制臺(tái)打印 rejected [Error:fulfilled]
當(dāng) function(fulfilled) 或者 function(rejected) 返回一個(gè) promise 時(shí),outputPromise 就會(huì)成為這個(gè)新的 promise.
這樣做的意義在于聚合結(jié)果 (Q.all),管理延時(shí),異?;謴?fù)等等
比如說(shuō)我們想要讀取一個(gè)文件的內(nèi)容,然后把這些內(nèi)容打印出來(lái)??赡軙?huì)寫出這樣的代碼:
// 錯(cuò)誤的寫法
var outputPromise = getInputPromise().then(function (fulfilled) {
fs.readFile('test.txt', 'utf8', function (err, data) {
return data;
});
});
然而這樣寫是錯(cuò)誤的,因?yàn)?function(fulfilled) 并沒(méi)有返回任何值。需要下面的方式:
var Q = require('q');
var fs = require('fs');
var defer = Q.defer();
/**
* 通過(guò) defer 獲得promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil時(shí),調(diào)用 function(fulfilled)
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected時(shí),調(diào)用 function(rejected)
* 將 then 返回的 promise 賦給 outputPromise
* function(fulfilled) 將新的 promise 賦給 outputPromise
* 未完成改變?yōu)?reject
* @private
*/
var outputPromise = getInputPromise().then(function (fulfilled) {
var myDefer = Q.defer();
fs.readFile('test.txt', 'utf8', function (err, data) {
if (!err && data) {
myDefer.resolve(data);
}
});
return myDefer.promise;
}, function (rejected) {
throw new Error('rejected');
});
/**
* 當(dāng) outputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled),控制臺(tái)打印 test.txt 文件內(nèi)容。
*
*/
outputPromise.then(function (fulfilled) {
console.log(fulfilled);
}, function (rejected) {
console.log(rejected);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
//defer.reject();
/**
* 將 inputPromise 的狀態(tài)由未完成變成 fulfilled
*/
defer.resolve(); // 控制臺(tái)打印出 test.txt 的內(nèi)容
方法傳遞
方法傳遞有些類似于 Java 中的 try 和 catch。當(dāng)一個(gè)異常沒(méi)有響應(yīng)的捕獲時(shí),這個(gè)異常會(huì)接著往下傳遞
方法傳遞的含義是當(dāng)一個(gè)狀態(tài)沒(méi)有響應(yīng)的回調(diào)函數(shù),就會(huì)沿著 then 往下找
沒(méi)有提供 function(rejected)
var outputPromise = getInputPromise().then(function (fulfilled) { })
如果 inputPromise 的狀態(tài)由未完成變成 rejected, 此時(shí)對(duì) rejected 的處理會(huì)由 outputPromise 來(lái)完成
var Q = require('q');
var fs = require('fs');
var defer = Q.defer();
/**
* 通過(guò)defer獲得promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 function(fulfilled)
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected 時(shí),這個(gè) rejected 會(huì)傳向 outputPromise
*/
var outputPromise = getInputPromise().then(function (fulfilled) {
return 'fulfilled'
});
outputPromise.then(function (fulfilled) {
console.log('fulfilled: ' + fulfilled);
}, function (rejected) {
console.log('rejected: ' + rejected);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
defer.reject('inputpromise rejected'); // 控制臺(tái)打印 rejected: inputpromise rejected
/**
* 將 inputPromise的狀態(tài)由未完成變成fulfilled
*/
//defer.resolve();
沒(méi)有提供 function(fulfilled)
var outputPromise = getInputPromise().then(null, function (rejected) { })
如果 inputPromise 的狀態(tài)由未完成變成 fulfilled, 此時(shí)對(duì) fulfil 的處理會(huì)由 outputPromise 來(lái)完成
var Q = require('q');
var fs = require('fs');
var defer = Q.defer();
/**
* 通過(guò)defer獲得promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil時(shí),傳遞給 outputPromise
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected時(shí),調(diào)用 function(rejected)
* function(fulfilled) 將新的 promise 賦給 outputPromise
* 未完成改變?yōu)?reject
* @private
*/
var outputPromise = getInputPromise().then(null, function (rejected) {
return 'rejected';
});
outputPromise.then(function (fulfilled) {
console.log('fulfilled: ' + fulfilled);
}, function (rejected) {
console.log('rejected: ' + rejected);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
// defer.reject('inputpromise rejected');
/**
* 將 inputPromise 的狀態(tài)由未完成變成fulfilled
*/
defer.resolve('inputpromise fulfilled'); // 控制臺(tái)打印fulfilled: inputpromise fulfilled
可以使用 fail(function(error)) 來(lái)專門針對(duì)錯(cuò)誤處理,而不是使用 then(null,function(error))
var outputPromise = getInputPromise().fail(function (error) { })
看這個(gè)例子:
var Q = require('q');
var fs = require('fs');
var defer = Q.defer();
/**
* 通過(guò)defer獲得promise
* @private
*/
function getInputPromise() {
return defer.promise;
}
/**
* 當(dāng) inputPromise 狀態(tài)由未完成變成 fulfil 時(shí),調(diào)用 then(function(fulfilled))
* 當(dāng) inputPromise 狀態(tài)由未完成變成 rejected 時(shí),調(diào)用 fail(function(error))
* function(fulfilled) 將新的 promise 賦給 outputPromise
* 未完成改變?yōu)閞eject
* @private
*/
var outputPromise = getInputPromise().then(function (fulfilled) {
return fulfilled;
}).fail(function (error) {
console.log('fail: ' + error);
});
/**
* 將 inputPromise 的狀態(tài)由未完成變成 rejected
*/
defer.reject('inputpromise rejected');// 控制臺(tái)打印 fail: inputpromise rejected
/**
* 將 inputPromise 的狀態(tài)由未完成變成 fulfilled
*/
//defer.resolve('inputpromise fulfilled');
可以使用 progress(function (progress)) 來(lái)專門針對(duì)進(jìn)度信息進(jìn)行處理,而不是使用 then(function (success) { }, function (error) { }, function (progress) { })
var Q = require('q');
var defer = Q.defer();
/**
* 獲取初始 promise
* @private
*/
function getInitialPromise() {
return defer.promise;
}
/**
* 為 promise 設(shè)置 progress 信息處理函數(shù)
*/
var outputPromise = getInitialPromise().then(function (success) {
}).progress(function (progress) {
console.log(progress);
});
defer.notify(1);
defer.notify(2); // 控制臺(tái)打印 1,2
promise 鏈
promise 鏈提供了一種讓函數(shù)順序執(zhí)行的方法
函數(shù)順序執(zhí)行是很重要的一個(gè)功能。比如知道用戶名,需要根據(jù)用戶名從數(shù)據(jù)庫(kù)中找到相應(yīng)的用戶,然后將用戶信息傳給下一個(gè)函數(shù)進(jìn)行處理
var Q = require('q');
var defer = Q.defer();
// 一個(gè)模擬數(shù)據(jù)庫(kù)
var users = [{ 'name': 'andrew', 'passwd': 'password' }];
function getUsername() {
return defer.promise;
}
function getUser(username) {
var user;
users.forEach(function (element) {
if (element.name === username) {
user = element;
}
});
return user;
}
// promise 鏈
getUsername().then(function (username) {
return getUser(username);
}).then(function (user) {
console.log(user);
});
defer.resolve('andrew');
我們通過(guò)兩個(gè) then 達(dá)到讓函數(shù)順序執(zhí)行的目的。
then 的數(shù)量其實(shí)是沒(méi)有限制的。當(dāng)然,then 的數(shù)量過(guò)多,要手動(dòng)把他們鏈接起來(lái)是很麻煩的。比如
foo(initialVal).then(bar).then(baz).then(qux)
這時(shí)我們需要用代碼來(lái)動(dòng)態(tài)制造 promise 鏈
var funcs = [foo, bar, baz, qux]
var result = Q(initialVal)
funcs.forEach(function (func) {
result = result.then(func)
})
return result
當(dāng)然,我們可以再簡(jiǎn)潔一點(diǎn)
var funcs = [foo, bar, baz, qux]
funcs.reduce(function (pre, current),Q(initialVal){
return pre.then(current)
})
看一個(gè)具體的例子
function foo(result) {
console.log(result);
return result + result;
}
// 手動(dòng)鏈接
Q('hello').then(foo).then(foo).then(foo);
// 控制臺(tái)輸出: hello
// hellohello
// hellohellohello
// 動(dòng)態(tài)鏈接
var funcs = [foo, foo, foo];
var result = Q('hello');
funcs.forEach(function (func) {
result = result.then(func);
});
// 精簡(jiǎn)后的動(dòng)態(tài)鏈接
funcs.reduce(function (prev, current) {
return prev.then(current);
}, Q('hello'));
對(duì)于 promise 鏈,最重要的是需要理解為什么這個(gè)鏈能夠順序執(zhí)行。如果能夠理解這點(diǎn),那么以后自己寫 promise 鏈可以說(shuō)是輕車熟路啊
promise 組合
回到我們一開(kāi)始讀取文件內(nèi)容的例子。如果現(xiàn)在讓我們把它改寫成 promise 鏈,是不是很簡(jiǎn)單呢?
var Q = require('q'),
fs = require('fs');
function printFileContent(fileName) {
return function () {
var defer = Q.defer();
fs.readFile(fileName, 'utf8', function (err, data) {
if (!err && data) {
console.log(data);
defer.resolve();
}
})
return defer.promise;
}
}
// 手動(dòng)鏈接
printFileContent('sample01.txt')()
.then(printFileContent('sample02.txt'))
.then(printFileContent('sample03.txt'))
.then(printFileContent('sample04.txt')); // 控制臺(tái)順序打印 sample01 到 sample04 的內(nèi)容
很有成就感是不是。然而如果仔細(xì)分析,我們會(huì)發(fā)現(xiàn)為什么要他們順序執(zhí)行呢,如果他們能夠并行執(zhí)行不是更好嗎? 我們只需要在他們都執(zhí)行完成之后,得到他們的執(zhí)行結(jié)果就可以了
我們可以通過(guò) Q.all([promise1,promise2...]) 將多個(gè) promise 組合成一個(gè) promise 返回。 注意:
1. 當(dāng) all 里面所有的 promise 都 fulfil 時(shí),Q.all 返回的 promise 狀態(tài)變成 fulfil
2. 當(dāng)任意一個(gè) promise 被 reject 時(shí),Q.all 返回的 promise 狀態(tài)立即變成 reject
我們來(lái)把上面讀取文件內(nèi)容的例子改成并行執(zhí)行吧
var Q = require('q');
var fs = require('fs');
/**
*讀取文件內(nèi)容
*@private
*/
function printFileContent(fileName) {
// Todo: 這段代碼不夠簡(jiǎn)潔。可以使用 Q.denodeify 來(lái)簡(jiǎn)化
var defer = Q.defer();
fs.readFile(fileName, 'utf8', function (err, data) {
if (!err && data) {
console.log(data);
defer.resolve(fileName + ' success ');
} else {
defer.reject(fileName + ' fail ');
}
})
return defer.promise;
}
Q.all([printFileContent('sample01.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])
.then(function (success) {
console.log(success);
}); // 控制臺(tái)打印各個(gè)文件內(nèi)容 順序不一定
現(xiàn)在知道 Q.all 會(huì)在任意一個(gè) promise 進(jìn)入 reject 狀態(tài)后立即進(jìn)入 reject 狀態(tài)。如果我們需要等到所有的 promise 都發(fā)生狀態(tài)后(有的 fulfil, 有的 reject),再轉(zhuǎn)換 Q.all 的狀態(tài), 這時(shí)我們可以使用 Q.allSettled
var Q = require('q'),
fs = require('fs');
/**
*讀取文件內(nèi)容
*@private
*/
function printFileContent(fileName) {
// Todo: 這段代碼不夠簡(jiǎn)潔??梢允褂肣.denodeify來(lái)簡(jiǎn)化
var defer = Q.defer();
fs.readFile(fileName, 'utf8', function (err, data) {
if (!err && data) {
console.log(data);
defer.resolve(fileName + ' success ');
} else {
defer.reject(fileName + ' fail ');
}
})
return defer.promise;
}
Q.allSettled([printFileContent('nosuchfile.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])
.then(function (results) {
results.forEach(
function (result) {
console.log(result.state);
}
);
});
結(jié)束 promise 鏈
通常,對(duì)于一個(gè) promise 鏈,有兩種結(jié)束的方式。第一種方式是返回最后一個(gè) promise
如 return foo().then(bar);
第二種方式就是通過(guò) done 來(lái)結(jié)束 promise 鏈
如 foo().then(bar).done()
為什么需要通過(guò) done 來(lái)結(jié)束一個(gè) promise 鏈呢? 如果在我們的鏈中有錯(cuò)誤沒(méi)有被處理,那么在一個(gè)正確結(jié)束的 promise 鏈中,這個(gè)沒(méi)被處理的錯(cuò)誤會(huì)通過(guò)異常拋出
var Q = require('q');
function getPromise(msg, timeout, opt) {
var defer = Q.defer();
setTimeout(function () {
console.log(msg);
if (opt)
defer.reject(msg);
else
defer.resolve(msg);
}, timeout);
return defer.promise;
}
/**
* 沒(méi)有用 done() 結(jié)束的 promise 鏈
* 由于 getPromse('2',2000,'opt') 返回 rejected, getPromise('3',1000) 就沒(méi)有執(zhí)行
* 然后這個(gè)異常并沒(méi)有任何提醒,是一個(gè)潛在的 bug
*/
getPromise('1', 3000)
.then(function () { return getPromise('2', 2000, 'opt') })
.then(function () { return getPromise('3', 1000) });
/**
* 用 done() 結(jié)束的 promise 鏈
* 有異常拋出
*/
getPromise('1', 3000)
.then(function () { return getPromise('2', 2000, 'opt') })
.then(function () { return getPromise('3', 1000) })
.done();
附錄:一個(gè) Promise 簡(jiǎn)單的應(yīng)用(Node.js筆記(5)promise)
附:Promises/A+ 規(guī)范
promise 代表一個(gè)異步操作的最終結(jié)果。主要通過(guò) promise 的 then 方法訂閱其最終結(jié)果的處理回調(diào)函數(shù),和訂閱因某原因無(wú)法成功獲取最終結(jié)果的處理回調(diào)函數(shù)。
更對(duì)詳細(xì)見(jiàn):Promises/A+
A 與 A+ 的不同點(diǎn)
- A+ 規(guī)范通過(guò)術(shù)語(yǔ) thenable 來(lái)區(qū)分 promise 對(duì)象
- A+ 定義 onFulfilled/onRejectd 必須是作為函數(shù)來(lái)調(diào)用,而且調(diào)用過(guò)程必須是異步的
- A+ 嚴(yán)格定義了 then 方法鏈?zhǔn)秸{(diào)用時(shí),onFulfilled/onRejectd 的調(diào)用順序
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Node.js實(shí)現(xiàn)簡(jiǎn)單聊天服務(wù)器
Node.js 是一個(gè)基于Chrome JavaScript運(yùn)行時(shí)建立的一個(gè)平臺(tái), 用來(lái)方便地搭建快速的,易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用,今天我們來(lái)探討下,如何使用node.js實(shí)現(xiàn)簡(jiǎn)單的聊天服務(wù)器2014-06-06
利用nodeJs anywhere搭建本地服務(wù)器環(huán)境的方法
今天小編就為大家分享一篇利用nodeJs anywhere搭建本地服務(wù)器環(huán)境的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
nodejs個(gè)人博客開(kāi)發(fā)第五步 分配數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了nodejs個(gè)人博客開(kāi)發(fā)的分配數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Node.js實(shí)現(xiàn)在目錄中查找某個(gè)字符串及所在文件
這篇文章主要介紹了Node.js實(shí)現(xiàn)在目錄中查找某個(gè)字符串及所在文件,文中代碼簡(jiǎn)潔,而且速度相當(dāng)?shù)目?需要的朋友可以參考下2014-09-09
詳解nodeJs文件系統(tǒng)(fs)與流(stream)
這篇文章主要介紹了詳解nodeJs文件系統(tǒng)(fs)與流(stream),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Nodejs進(jìn)階:核心模塊net入門學(xué)習(xí)與實(shí)例講解
本篇文章主要是介紹了Nodejs之NET模塊,net模塊是同樣是nodejs的核心模塊,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-11-11

