使用 promises 索引映射 Promise.all 输出

Posted

技术标签:

【中文标题】使用 promises 索引映射 Promise.all 输出【英文标题】:Map Promise.all output with promises index 【发布时间】:2018-04-27 09:16:51 【问题描述】:

我正在使用支持默认异步等待代码样式的 nodejs v8+。

在我的问题中,我试图将所有承诺推送到一个数组中,然后使用 Promise.all 和 await 关键字来获取响应。但问题是,我无法用键映射承诺。

示例如下:

let users = ["user1", "user2", "user3"];

    let promises = [];
    for(let i = 0; i < users.length; i++)
      let response = this.myApiHelper.getUsersData(users[i]);
      promises.push(response);
    
    let allResponses = await Promise.all(promises);

在这里我得到了所有响应的所有收集响应,但我实际上想按用户映射它。 例如,目前我正在以这种格式获取数据:

[

  user1 Data from promise 1
,

  user2 Data from promise 2
,

  user3 Data from promise 3

]

但我想要这种格式的数据:

[
 
  "user1": Data from promise 1
 ,
 
   "user2": Data from promise 2
 ,
 
   "user3": Data from promise 3
 
]

我确信必须有一种方法来映射用户的每一个承诺,但我不知道。

【问题讨论】:

【参考方案1】:

我们将创建一个用户数组。迭代它以创建一个 Promise 数组,我们将其提供给 Promise.all。然后迭代答案以创建一个将用户与来自getUsersData 的相关答案匹配的对象。

关于 Promise.all 要了解的是,返回数据的顺序取决于它的条目中给出的promises 的顺序。


const users = ['user1', 'user2', 'user3'];

const rets = await Promise.all(users.map(x => this.myApiHelper.getUsersData(x)));

const retWithUser = rets.map((x, xi) => (
   user: users[xi],
   ret: x,
));

Here你有一个关于数组方法的很棒的教程(map, filter, some...)

【讨论】:

【参考方案2】:

虽然我接受的答案是解决方案之一,但我认为它是完美的,我将保留为已接受的答案,但我想发布我的解决方案,我后来发现它更简单:

我们可以简单地使用这个:

let finalData = ;
let users = ["user1", "user2", "user3"];
await Promise.all(users.map(async(eachUser) => 
    finalData[user] = await this.myApiHelper.getUsersData(eachUser);
))
console.log(finalData);

【讨论】:

【参考方案3】:

如此处所述 How to use Promise.all with an object as input

这是一个简单的 ES2015 函数,它接受一个具有可能是 Promise 的属性的对象,并返回该对象的 Promise 以及已解析的属性。

function promisedProperties(object) 

  let promisedProperties = [];
  const objectKeys = Object.keys(object);

  objectKeys.forEach((key) => promisedProperties.push(object[key]));

  return Promise.all(promisedProperties)
    .then((resolvedValues) => 
      return resolvedValues.reduce((resolvedObject, property, index) => 
        resolvedObject[objectKeys[index]] = property;
        return resolvedObject;
      , object);
    );


然后你会像这样使用它:

var promisesObject = ;
users.map((element, index) => object[element] = this.myApiHelper.getUsersData(users[index]));
promisedProperties(object).then(response => console.log(response));

请注意,首先您需要一个带有 key/promise 的对象。

【讨论】:

虽然我没有投反对票,这似乎是一个可行的解决方案,但同时它有点复杂。所以接受了一个简单的解决方案

以上是关于使用 promises 索引映射 Promise.all 输出的主要内容,如果未能解决你的问题,请参考以下文章

Promise和Observable的映射

在 Javascript 数组映射中使用 promise 函数

React 帮助:在映射数组中使用 Promise 进行条件渲染 [关闭]

使用 promise 和 async-await 映射来自其他表的嵌套数据

向 Promise.all 添加计时器,映射

带有嵌套地图的 Promise.all .. 第一张地图仅适用于其他人在猫鼬中返回空对象