节点回调以 async/await 承诺

node callback to promise with async/await

本文关键字:await 承诺 async 回调 节点      更新时间:2023-09-26

我正在尝试编写一个简单的函数,将节点样式的回调函数转换为承诺,因此我可以将它们与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) => {
     ... });

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

问题当然是匹配计算为未定义,显然承诺在 await 语法行后得到解决。

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

自节点 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

您的问题是您正在异步回调中构造newPromise。因此,当您归还它时,您仍然undefined。相反,您需要立即调用 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);
    });
}

另请参阅如何将现有回调 API 转换为承诺?