util.promise

在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型式返回

This entry was posted in nodejs. Bookmark the permalink.

Leave a Reply