用 async/await 承诺的节点回调

node callback to promise with async/await

我正在尝试编写一个简单的函数,将节点样式的回调函数转换为承诺,以便我可以将它们与 async/await 一起使用。

当前代码:

function toPromise(ctx, func, ...args) {
  let newPromise;

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

   func.apply(ctx, args);

   return newPromise;
}

用法示例:

const match = await toPromise(user, user.comparePassword, password);
//trying to avoid the following:
user.comparePassword(password, (err, res) => {
     ... });

对于一些很棒的库来说,这可能没有任何意义,但我只是想将其编码为练习。

问题当然是 match 求值为未定义,显然 promise 在 await 语法行之后得到解决。

知道如何解决这个问题吗?

您的问题是您正在构造 newPromise 异步回调内部。所以 you've still got undefined 当你 return 它。相反,您需要立即调用 Promise 构造函数,并且只将 resolve/reject 放在异步回调中:

function toPromise(ctx, func, ...args) {
    return new Promise((resolve, reject) => {
        args.push((err, res) => {
            if (err) reject(err);
            else resolve(res);
        });
        func.apply(ctx, args);
    });
}

另见 How do I convert an existing callback API to promises?

从节点 v8.0.0 开始,他们添加了 util.promisify

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

const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});

参考:https://nodejs.org/api/util.html#util_util_promisify_original