您当前的位置:首页 > 计算机 > 编程开发 > JavaScript

Node.js 中的 util.promisify() 函数介绍

时间:12-14来源:作者:点击数:

Node.js 的内置 util 包有一个 promisify() 函数 转换 回调 基于 Promise 函数的函数。 这使您可以将 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() 函数到返回回调的函数:

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

// Convert `fs.readFile()` into a function that takes the
// same parameters but returns a promise.
const readFile = util.promisify(fs.readFile);

// You can now use `readFile()` with `await`!
const buf = await readFile('./package.json');

const obj = JSON.parse(buf.toString('utf8'));
obj.name; // 'masteringjs.io'

假设

如何 util.promisify() 在引擎盖下工作? 有一个 polyfill ,你可以在 这里阅读完整的实现 。您也可以在 此处找到 Node.js 实现 ,尽管出于教育目的,polyfill 更易于阅读。

背后的关键思想 util.promisify() 就是它 给你传入的参数增加了一个回调函数 。该回调函数解析或拒绝承诺函数返回的承诺。这有点拗口,所以这是一个非常简化的自定义实现示例 util.promisify()

const fs = require('fs');

// A simplified implementation of `util.promisify()`. Doesn't
// cover all cases, don't use this in prod!
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 != null) {
          return reject(err);
        }
        resolve(res);
      }]));
    });
  };
}

// Convert `fs.readFile()` into a function that takes the
// same parameters but returns a promise.
const readFile = promisify(fs.readFile);

// You can now use `readFile()` with `await`!
const buf = await readFile('./package.json');

const obj = JSON.parse(buf.toString('utf8'));
obj.name; // 'masteringjs.io'

那么这是什么意思?

第一 util.promisify() 向您传入的参数添加 1 个额外参数,然后使用这些新参数调用原始函数。 这意味着底层函数需要支持该数量的参数。 所以如果你正在调用一个 Promise 函数 myFn() 有 2 个类型的参数 [String, Object],确保原始函数支持调用签名 [String, Object, Function]

第二 util.promisify() 对 函数上下文 。

失去上下文

丢失上下文 意味着函数调用以错误的值结束 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` instead of a `MyClass` instance!

请记住 this 包含该函数在调用时的属性的任何对象。 因此您可以通过将 promisified 函数设置为同一对象的属性来保留上下文:

class MyClass {
  myCallbackFn(cb) {
    cb(null, this);
  }
}

const obj = new MyClass();
// Retain context because `promisified` is a property of `obj`
obj.promisified = require('util').promisify(obj.myCallbackFn);

const context = await obj.promisified();
context === obj; // true
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐