如何把函數(shù)都用promise方式實現(xiàn)批狱?
我覺得這是一個好問題。當前在我所在的公司展东,只要用 NodeJS
進行開發(fā)赔硫,從框架到具體的應用實例到工具,已經(jīng)全部遷移到以 promise
為中心開發(fā)方式盐肃。帶來的好處是大家都使用 promise
進行異步方案的解決爪膊,不用再考慮回調(diào)( callback
)。
但是事情總有特例砸王,現(xiàn)實npm
上推盛,還是有很多的庫還沒有用promise
進行實現(xiàn),如:node
中的標準庫处硬。這樣讓使用者很難受小槐,用著用著 promise
出現(xiàn)了一個 callback
拇派,你會覺得世界為什么就這么亂呢荷辕?
神說要有光凿跳,于是就有了光!我也想說疮方,大神說要解決控嗜,于是就有了 promoisify
!
1 什么是 promisify
簡單來說: promisify
就是把帶有 callback
函數(shù)骡显,變成重新用 promise
來實現(xiàn)的一種技術(shù)方案疆栏,它能一勞永逸的解決:如何把函數(shù)都用 promise
重新實現(xiàn)的問題。
2 promisify 的使用
promisify
的使用惫谤,當然脫離不了某一個 promise
的實現(xiàn)壁顶。在這里,我選擇 bluebird
溜歪。因為它足夠強大若专,學習使用 promise
,就它足夠了蝴猪。
下面來說說:bluebird
中有關(guān)promisify
的一些方法调衰。
在bluebird
的API
中,兩個方法可以幫助你自阱,它們分別是:promiseify 和 promisifyall嚎莉。
2.1 promisify
prmoisify
的作是:將一個 nodeCallback
形式函數(shù)調(diào)用轉(zhuǎn)為 promise
。
這里需要解釋一下: nodeCallback
是什么意思沛豌。
nodeCallback
是 Nodojs
中的一個常用詞趋箩。表達是意思是:Nodejs
中,以錯誤優(yōu)先的回調(diào)函數(shù)的總稱加派。
它包括兩個意思:
-
nodeCallback
回調(diào)函數(shù)簽名阁簸。 -
nodeCallBack
回調(diào)函數(shù)出現(xiàn)的位置。
nodeCallback 簽名
該回調(diào)函數(shù)的簽名一定是這樣:
// 這樣是對的
function fooCallBack(err, a, b){
// something
console.log(a,b);
}
// 這樣不對
function foo1CallBack(a,b,err){
}
可以看到哼丈,fooCallBack
函數(shù)的調(diào)用參數(shù)中启妹,第一個參數(shù)是: err
, 也就是說的 noodeCallBack
函數(shù)的第一個參數(shù)一定傳入的是 err
,而不能是別的參數(shù)醉旦。只要滿足了這個條件饶米,都可叫 nodeCallback
。
nodeCallBack 出現(xiàn)的順序
nodeCallBack
一定出現(xiàn)在異步函數(shù)的最后一個车胡,也就是這樣:
// 這樣是對的檬输。
function foo(a,b,nodeCallback){
// pass
}
// 這樣就不是 nodeCallback
function foo(a,nodeCallback,b){
// pass
}
只要滿足了簽名和順序,就可以叫做 nodeCallBack
匈棘。
那 nodeCallback
存在哪里呢丧慈?告訴你吧,所有的 NodeJS
標準包中異步的地方都是它。
好了說了這么多 nodeCallback
逃默,現(xiàn)在來說說 promosify
怎樣使用:
const Promise = require('bluebird');
const fs = require('fs');
// 回調(diào)形式鹃愤,這里的callback 就是 nodeCallback
fs.readFile('./test.js',function(err,data){
console.log(data);
});
// promisify 形式
const readFileAsync = Promise.promisify(fs.readFile);
readFileAsync('./test.js').then(function(data){
console.log(data);
}).catch(console.log);
很簡單吧。具體實現(xiàn)就不說了完域,想要了解的去 google
吧软吐。
2.2 promisifyall
如果說 promisify
只能一次轉(zhuǎn)一個函數(shù),那 promisifyall
的作用就是一次把一個庫的文件轉(zhuǎn)完吟税。
說的更清楚一點凹耙,promisifyall
能把一個庫中有函數(shù)全部變成 promise
的形式,改變后的函數(shù)都帶上了 Async
的后綴肠仪⌒けВ看代碼:
const Promise = require('bluebird');
const fs = Promise.promisifyall(require('fs'));
fs.readFileAsync('./test.js').then(function(data){
console.log(data);
}).catch(console.log);
從上面可以知道:fs
這個標準庫,經(jīng)過 promisifyall
, 所有的函數(shù)都已經(jīng)被 promise
化了异旧。而被 promise
化的函數(shù)名變成了:原來的函數(shù)名+Async
虐沥。
3 結(jié)論
當學會使用 promisify
和 promisifyall
這兩個方法,我相信大家以后都對:如何把函數(shù)都用promise方式實現(xiàn)泽艘?
這樣的問題胸有成竹了吧欲险。