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 的回調風格,全部函數均可以這樣轉換。也就是說,知足下面兩個條件便可。函數
結合 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();