Node.js 內建的 util 套件有一個 promisify() 函數,可以將基於回呼的函數轉換為基於 Promise 的函數。本文就來跟大家介紹一下Node.js 中的 util.promisify() 函數,希望對大家有幫助。
讓你可以使用 Promise 鍊式 和 async/await 與基於回呼的 API。
例如,Node.js 的 fs 套件 使用回呼。通常,讀取檔案需要使用回呼方式:
const fs = require('fs'); fs.readFile('./package.json', function callback(err, buf) { const obj = JSON.parse(buf.toString('utf8')); obj.name; // 'masteringjs.io' });
你可以使用util.promisify()
將fs.readFile()
函數轉換為傳回Promise 的函數。 【相關教學推薦:nodejs影片教學、程式設計教學】
const fs = require('fs'); const util = require('util'); // 将 `fs.readFile()` 转换为一个函数,该函数接受相同的参数但返回一个 Promise const readFile = util.promisify(fs.readFile); // 现在可以对 `readFile()` 使用 `await` 了! const buf = await readFile('./package.json'); const obj = JSON.parse(buf.toString('utf8')); obj.name; // 'masteringjs.io'
##util.promisify()在內部是如何運作的?
npm 上有一個 polyfill,你可以 在這裡閱讀完整的實作。你也可以 在這裡找到 Node.js 的實作,不過出於教育目的,polyfill 比較容易閱讀。
util.promisify() 的核心思想是
在你傳遞的參數基礎上加入了一個回呼函數。這個回呼函數解析(resolve)或拒絕(rejected) promisified 函數傳回的 Promise。
util.promisify() 方法一個簡化的實作版本。
const fs = require('fs'); // `util.promisify()` 的简化实现。不涵盖所有情况,不要在生产环境中使用! function promisify(fn) { return function () { const args = Array.prototype.slice.call(arguments); return new Promise((resolve, reject) => { fn.apply(this, [].concat(args).concat([(err, res) => { if (err) { return reject(err); } resolve(res); }])); }); } } // 将 `fs.readFile()` 转换为一个函数,该函数接受相同的参数但返回一个 Promise const readFile = util.promisify(fs.readFile); // 现在可以对 `readFile()` 使用 `await` 了! const buf = await readFile('./package.json'); const obj = JSON.parse(buf.toString('utf8')); obj.name; // 'masteringjs.io'怎麼理解?首先,
util.promisify() 會向你傳遞的參數新增 1 個額外參數,然後使用這些新參數呼叫原始函數。那麼底層函數就要支援這些數量的參數調用,舉例:如果你正在使用類型為
[String,Object] 的2 個參數調用promisified 函數
myFn(),請確保原始函數支援呼叫簽名
[String, Object, Function]。
util.promisify() 對於
函數上下文 有影響。
遺失上下文(Losing Context) 表示呼叫函數時內部 this 值不正確 。遺失上下文是轉換後的函數的常見問題:
class MyClass { myCallbackFn(cb) { cb(null, this); } } const obj = new MyClass(); const promisified = require('util').promisify(obj.myCallbackFn); const context = await promisified(); context; // 打印 `undefined` 而非 `MyClass` 实例!
this 表示函數被呼叫時所屬的物件
。因此,你可以透過將 promisified 函數設定為相同物件的屬性來保留上下文:
class MyClass { myCallbackFn(cb) { cb(null, this); } } const obj = new MyClass(); // 保留上下文,因为 `promisified` 是 `obj` 的一个属性 obj.promisified = require('util').promisify(obj.myCallbackFn); const context = await obj.promisified(); context === obj; // true更多node相關知識,請造訪:
nodejs 教學!
以上是深入淺析Node中的util.promisify()函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!