Node.js 8 中的 util.promisify的詳解

Node.js 8帶來了 不少新特性 。其中比較值得注意的,便有 util.promisify() 這個方法。node

util.promisify()git

雖然 Promise 已經普及,可是 Node.js 裏仍然有大量的依賴回調的異步函數,若是咱們每一個函數都封裝一次,還麻煩。github

因此 Node8 就提供了 util.promisify() 這個方法,方便咱們快捷的把原來的異步回調方法改爲返回 Promise 實例的方法,接下來,想繼續用隊列,仍是 await 就看須要了。小程序

例如 讀取文件狀態的操做:promise

var fs = require("fs");
 //讀取文件的狀態;
 fs.stat(path,callback);異步

fs.stat("./wenjian.txt",function(err,stats){
    console.log(err);
    console.log(stats);
//    獲取文件的大小;
    console.log(stats.size);
//    獲取文件最後一次訪問的時間;
    console.log(stats.atime.toLocaleString());
//    文件建立的時間;
    console.log(stats.birthtime.toLocaleString());
//    文件最後一次修改時間;
    console.log(stats.mtime.toLocaleString());
//    狀態發生變化的時間;
    console.log(stats.ctime.toLocaleString())
//判斷是不是目錄;是返回true;不是返回false;
    console.log(stats.isFile())
//    判斷是不是文件;是返回true、不是返回false;
    console.log(stats.isDirectory())
})  

將讀取文件狀態的回調函數經過util來promise化:async

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);
stat('./path').then((stats) => {
  // Do something with `stats`
 }).catch((error) => {
  // Handle the error.
 });

 

只要符合 Node.js 的回調風格,全部函數均可以這樣轉換。也就是說,知足下面兩個條件便可。函數

  1. 最後一個參數是函數
  2. 回調函數的參數爲 (err, result),前面是可能的錯誤,後面是正常的結果

結合 Await/Async 使用ui

一樣是上面的例子,若是想要結合 Await/Async,能夠這樣使用:spa

const util = require('util');
const fs = require('fs');
 
const stat = util.promisify(fs.stat);
async function readStats(dir) {
 try {
  let stats = await stat(dir);
  // Do something with `stats`
 } catch (err) { // Handle the error.
  console.log(err);
 }
}
readStats('./path');  //調用

自定義 Promise 化處理函數

那若是函數不符合這個風格,還能用 util.promisify() 麼?答案也是確定的。咱們只要給函數增長一個屬性,util.promisify.custom ,指定一個函數做爲 Promise 化處理函數,便可。請看下面的代碼:

const util = require('util');
 
function doSomething(foo, callback) {
 // ...
}
 
doSomething[util.promisify.custom] = function(foo) {
 return getPromiseSomehow();
};
 
const promisified = util.promisify(doSomething);
console.log(promisified === doSomething[util.promisify.custom]);
// prints 'true'

 

如此一來,任什麼時候候咱們對目標函數 doSomething 進行 Promise 化處理,都會獲得以前定義的函數。運行它,就會按照咱們設計的特定邏輯返回 Promise 實例。

咱們就能夠升級之前全部的異步回調函數了。

Promise 介紹

由於種種歷史緣由,JS 當中有大量異步函數。這些異步函數,大多要依賴回調進行處理(這裏我以爲把事件偵聽算做回調也是合理的),可是回調嵌套層次一多,就會造成所謂的「回調陷阱」,讓開發者苦不堪言。

 爲了解決這個問題,開發社區通過摸索,總結出來一套名爲 Promise/A+ 的解決方案。大致上來講,這套方案經過使用 「Promise 回調實例」包裹原先的回調函數,能夠將原先複雜的嵌套展開、鋪平,從而下降開發和維護的難度和成本。

ES2015(ES6)裏包含了 Promise 標準,現在已經在大部分運行時裏實裝,咱們能夠放心大膽的使用它。並且,因爲 Promise 不須要新的語法元素,因此即便在不支持原生 Promise 的環境裏也可使用類庫,好比 Q 或者 Bluebird ,甚至 jQuery 。

在小程序裏也有效喲。

ES2017 增長了 Await/Async 語法,但請注意, Await 後面必須跟 Promise 實例才能實現異步。因此,你們仍是把 Promise 的概念學好吧!

function resolveAfter2Seconds(x) {
 return new Promise(resolve => {
  setTimeout(() => {
   resolve(x);
  }, 2000);
 });
}
 
async function f1() {
 var x = await resolveAfter2Seconds(10);
 console.log(x); // 10
}
f1();

 

 原文

相關文章
相關標籤/搜索