你如何等待 return 一个值直到 promise 被解决?

How do you wait to return a value until promise is resolved?

我正在尝试编写一个函数,它 return 在函数内部的 Promise 已解决之前没有值。这是我正在尝试做的一个简化示例。

'use strict';

function get(db, id) {
     let p = db.command('GET', 'group:${id}');
     p.then(g => {
         g.memberNames = [];
         g.members.forEach(id => {
             User.get(db, id)
                 .then(profile => g.memberNames.push(profile.name))
                 .catch(err => reject(err));
         });
         return g;
    });
}

这是一个请求组 ID 和 return 为该组的数据的函数。在此过程中,它还将用户名放入数据结构中以显示他们的名字而不是他们的用户 ID。我的问题是这是 运行 异步的,将跳过 .then 回调。当它到达 return 时,g none 的回调已被调用并且 g.memberNames 仍然是空的。有没有办法让函数等待 return g 直到所有回调都被调用?

我看过很多关于 await 的资料。这里有必要吗?非常不希望将其他库添加到我的项目中。

由于您对 return 所有配置文件名称的操作也是异步的,因此您应该 return 在所有其他异步操作完成时完成承诺(或在其中一个被拒绝时拒绝)完成Promise.all

function get(db, id) {
  let p = db.command('GET', 'group:${id}');
  return p.then(g => {
    return Promise.all(g.members.map(id => {
      // NOTE: id is shadowing the outer function id parameter
      return User.get(db, id).then(profile => profile.name)
    })
  })
}

Is there a way to make the function wait to return g until all callbacks have been called?

是的,有。但是你应该改变你的思维方式,从“等到所有的回调都被调用”到“等到所有的承诺都被实现”。事实上,Promise.all 函数很简单地做到了这一点——它需要一个承诺数组和 returns 一个用结果数组解析的新承诺。

在你的情况下,它将是

function get(db, id) {
     return db.command('GET', 'group:${id}').then(g => {
         var promises = g.members.map(id => {
//                                ^^^ never use `forEach`
             return User.get(db, id).then(profile => profile.name);
//           ^^^^^^ a promise for the name of that profile
         });
         //
         return Promise.all(promises).then(names => {
//                                    ^^^^^^^^^^ fulfills with an array of the names
             g.memberNames = names;
             return g;
         });
    });
}