简单实现 Promisfy

在 Node.js 中,不少异步函数只支持回调函数形式的用法,比如 readFile。

采用回调函数会导致函数不断嵌套,降低了代码的可读性。

目前处理异步的方式一般是采用 Promise,它可以很好地解决这个问题。

将回调函数 Promisfy

把仅支持回调函数的函数变成 Promise 的形式,也成为 Promisfy。

在说明如何构造它之前,我们先来看看 Promisfy 的用法。

可以看到,利用 Promisfy 装饰之后,

就可以像使用 Promise 一样使用这个异步函数。

Promisfy 原理



装饰异步函数

pify(fs.readFile)('package.json', 'utf8') 

此刻对应的代码是

module.exports = fn => {
  return function(...args) {
      return new Promise(...);
  };
};

这里首先会对传入的函数进行类似装饰的操作,返回一个新的函数,记做 F。

F 会将传入的参数全部计入 args 数组。

在我们的例子中, args 就会赋值为 [‘package.json’ , ‘utf8’] 。

当 F 被调用后,会返回一个 Promise 对象。

压入自定义回调函数

再来看看 Promise 这部分。

...
    return new Promise((resolve, reject) => {
        args.push((err, result) => {
        if (err) {
            reject(err);
        } else {
            resolve(result);
        }
        });

        fn.apply(this, args);
    });
...

这个 Promise 对象在调用 then 方法执行时,会在 args 中压入一个回调函数。

这个回调函数的格式必须和修饰的异步函数的格式一样。

并在这个回调函数中,调用 Promise 对象的 resolve 和 reject 方法。

执行函数

最后,利用 fn.apply 方法调用 args 直接执行异步函数。

由于我们对 args 数组做了修改,在最后压入了自定义的回调函数。

那么在执行时,异步函数就会调用这个回调函数,

而这个回调函数,又会利用 then 中自定义的 resolve 和 reject 方法。

从而输出 package.json 的结果。

最后

可以访问这个仓库,调试本文的代码。其中测试部分用到了 Jest

发表评论

电子邮件地址不会被公开。 必填项已用*标注