我使用的是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
}
]
我确信一定有一种方法来映射用户的每个承诺,但我不知道。
我们将创建一个用户数组。对其进行迭代以创建一个由
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,
}));
这里你有一个关于数组方法的很棒的教程
(map, filter, some...)
。
虽然我接受的答案是解决方案之一,我认为这是完美的,我将保留为已接受的答案,但我想发布我后来发现的更简单的解决方案:
我们可以简单地使用这个:
let finalData = {};
let users = ["user1", "user2", "user3"];
await Promise.all(users.map(async(eachUser) => {
finalData[user] = await this.myApiHelper.getUsersData(eachUser);
}))
console.log(finalData);
如此处所述 如何使用 Promise.all 并以对象作为输入
这是一个简单的 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 的对象。