The built-in util package of Node.js has a promisify() function that can convert callback-based functions into Promise-based functions. This article will introduce you to the util.promisify() function in Node.js. I hope it will be helpful to you.
Allows you to use Promise chaining and async/await with callback-based APIs.
For example, Node.js's fs package uses callbacks. Usually, reading a file requires the use of a callback:
const fs = require('fs'); fs.readFile('./package.json', function callback(err, buf) { const obj = JSON.parse(buf.toString('utf8')); obj.name; // 'masteringjs.io' });
You can use util.promisify()
to convert the fs.readFile()
function into a function that returns a Promise . [Related tutorial recommendations: nodejs video tutorial, Programming teaching]
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()
How does it work internally? There is a polyfill available on npm and you can read the full implementation here. You can also find the Node.js implementation here, but for educational purposes the polyfill is easier to read.
util.promisify() The core idea is to
add a callback function based on the parameters you pass. This callback function resolves or rejects the Promise returned by the promisified function.
util.promisify() method.
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() will add 1 extra parameter to the parameters you passed, and then call the original function with these new parameters. Then the underlying function must support these number of parameter calls. For example: if you are calling the promisified function
myFn() with 2 parameters of type
[String, Object], please make sure Primitive functions support the calling signature
[String, Object, Function].
util.promisify() has an impact on
function context.
Losing Context Indicates that the internal this value is incorrect when the function is called. Losing context is a common problem with transformed functions:
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 represents the object
the function was called on. Therefore, you can preserve the context by setting the promisified function to a property of the same object:
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
nodejs tutorial!
The above is the detailed content of An in-depth analysis of the util.promisify() function in Node. For more information, please follow other related articles on the PHP Chinese website!