promise
promise
一個標準,它描述了異步調用的返回結果,包括正確返回結果和錯誤處理。關於詳細的說明文檔能夠參考Promises/A+。目前實現promise
標準的模塊有不少,如Q、bluebird和Deferred,下面咱們以Q爲例,介紹一下promise
在 nodejs
中的使用方法。node
###將通常的異步調用的函數轉換爲promise
風格的函數 好比通常狀況下,咱們異步讀取文件會寫出下面的代碼:git
fs.readFile("test.txt",function(err,data){ if(!err){ console.log(data); }else{ console.error(err); } });
咱們能夠把fs.readFile
函數封裝爲promise
風格的函數,以下:github
var preadFile = function(file){ fs.readFile(file,function(err,data){ var deferred = Q.defer(); if(!err){ deferred.resolve(data); }else{ deferred.reject(err); } return deferred.promise; }); }
這樣咱們就能夠這樣調用這個方法了:promise
//then 的第一個參數是正確處理函數,第二個參數是錯誤處理函數 preadFile("test.txt").then(console.log,console.error);
能夠看到這樣調用更加直接明瞭。異步
###使用方法函數
各個回調函數順序傳遞數據: 在nodejs
中咱們回去數據時,時常遇回調函數的返回結果須要傳遞給下一個回調函數,到時很大的回調函數嵌套,promise
能夠很輕鬆的在回調函數之間傳遞參數,看下面的例子:ui
var fun1 = function (data,cb) { cb(null,data+" fun1"); } var fun2 = function (data,cb) { cb(null,data+" fun2"); } var fun3 = function (data,cb) { cb(null,data+" fun3"); } function main(data,cb){ fun1(data,function(err,data){ if(!err){ fun2(data,function(err,data){ if(!err){ fun3(data,cb); }else{ cb(err); } }); }else{ cb(err); } }); }
能夠看到main
函數爲了獲得數據,須要嵌套調用fun1
,fun2
和fun3
,若是須要調用不少函數,那麼會造成很大的回調函數嵌套調用,致使代碼看起來很醜陋,並且不容易維護,下面咱們改用promise
重寫這段代碼:code
var Q = require("q"); var fun1 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun1"); return deferred.promise; } var fun2 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun2"); return deferred.promise; } var fun3 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun3"); return deferred.promise; } function main(data,cb){ fun1("test") .then(fun2) .then(fun3) .done(function(data){ cb(null,data);//ok 得到的最終數據爲 --->"test fun1 fun2 fun3" },function(err){ cb(err);//failed }); }
收集各個回調函數產生的數據:有時候咱們須要執行不少回調函數,然手把這個回調函數的數據一齊傳遞給一個函數處理,此時咱們能夠使用all
和spread
方法,參看以下代碼:文檔
var Q = require("q"); var fun1 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun1"); return deferred.promise; } var fun2 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun2"); return deferred.promise; } var fun3 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun3"); return deferred.promise; } Q.all([ fun2("test1"),fun3("test2"),fun4("test3") ]).spread(function(){ console.log(arguments);//得到的參數爲('test1 fun1', 'test2 fun2', 'test3 fun3' ) });
統一處理錯誤:傳統的回調函數方式使用的話,咱們須要在每個回調函數裏判斷是否有錯誤須要處理,這樣會存在不少冗餘代碼,使用promise
的話,能夠使用done
或者fail
統一在一個函數中處理錯誤,如第一個例子同樣,使用done
方法的第二個參數處理錯誤。get