在nodejs裡,大部分的io相關function是async,async透過callback返回處理結果, 因此在流程處理上容易因為連續多個async造成callback hell, 有些方式可以減緩這樣的問題:例如
- async套件(https://www.npmjs.com/package/async),
- ES2015的promise
- ES2017的async await
都是處理這類的問題(async await在nodejs 7.6+支援)。 而promise和async await又能夠很好的配合使用。透過async await能夠大幅地消除callback hell, 並且很接近synchronous call的編寫流程。
但大多數的nodejs io function都是callback style的,無法直接被async await利用。 在nodejs8中有提供一個util function: util.promisify 能夠將callback style function轉成promise
var util = require('util');
var fs = require('fs');
var fswriteFile = util.promisify(fs.writeFile);
<strong>async </strong>function main(){
try{
<strong>await </strong>fswriteFile('test.txt', 'hello world'); //await promise
console.log('write successfully'); //上面的promise resolve後才會走到這一行
}catch(e){
console.log(e);
}
}
main();
util.promisify使用時對於大部分callback style function FUNC(arg1, arg2, arg3…, callback) 不需特別注意,但少數callback參數不是在最後一個,則可以透過指定util.promisify.custom 告訴util.promisify要使用特定的promise
事實上可參考 setTimeout, setImmediate
{ [Function: setTimeout] [Symbol(util.promisify.custom)]: [Function] }
以下給出一個範例
var util = require('util');
function setTimeout1(ms){
return new Promise(function(resolve, reject){
setTimeout0(resolve, ms);
});
}
function setTimeout0(callback, ms){
setTimeout(callback, ms);
}
setTimeout0[util.promisify.custom] = setTimeout1;
var setTimeoutP = util.promisify(setTimeout0);
console.log(setTimeoutP == setTimeout1);
對於像dns.lookup在callback中有多個value回傳的,nodejs也定義了customPromisifyArgs,使得promise回傳會將多個值以object key value型式返回
