[英]Convert nested 'for' loops into a Promise, for a Promise? Nested Promises?
[英]Handling promise in nested loops
我是Promise的新手。 我有一个场景,其中另一个对象列表中的对象列表应根据外部api的响应进行更新。
我试图模拟一个示例场景,如下所示。 在下面的代码中,我有航班列表,其中必须通过添加新字段来更新Flights数组中的destlist数组,这些字段将基于userId从users数组中获取。 以下是codepen网址。
const flights = [ { data: { legid: 1, name: "A380", destlist: [ { city: "city1", userId: 1 }, { city: "city2", userId: 2 } ] } }, { data: { legid: 2, name: "A380", destlist: [ { city: "city1", userId: 2 } ] } } ]; const users = [ { id: 1, name: "Andrew", schoolId: 101 }, { id: 2, name: "Jessica", schoolId: 999 } ]; const getUser = id => { return new Promise((resolve, reject) => { const user = users.find(user => user.id === id); if (user) { setTimeout(() => resolve(user), 1000); } else { setTimeout(() => reject(`Unable to find user with id of ${id}.`), 1000); } }); }; prettyJSON( Promise.all( flights.map(function(flt) { return Promise.all( flt.data.destlist.map(function(item) { getUser(item.userId) .then(us => (item.name = us.name)) .catch(err => console.log(err)); return flt; }) ); }) ).then(function(data) { prettyJSON(data); }) ); function prettyJSON(obj) { console.log(JSON.stringify(obj, null, 2)); }
https://codepen.io/prabuj201987/pen/mGvRjL?editors=1012
电流输出
[
[
{
'data': {
'legid': 1,
'name': 'A380',
'destlist': [
{
'city': 'city1',
'userId': 1
},
{
'city': 'city2',
'userId': 2
}
]
}
},
{
'data': {
'legid': 1,
'name': 'A380',
'destlist': [
{
'city': 'city1',
'userId': 1
},
{
'city': 'city2',
'userId': 2
}
]
}
}
],
[
{
'data': {
'legid': 2,
'name': 'A380',
'destlist': [
{
'city': 'city1',
'userId': 2
}
]
}
}
]
]
预期产量
[
[
{
"data": {
"legid": 1,
"name": "A380",
"destlist": [
{
"city": "city1",
"userId": 1,
"name": "Andrew"
},
{
"city": "city2",
"userId": 2,
"name": "Jessica"
}
]
}
},
{
"data": {
"legid": 1,
"name": "A380",
"destlist": [
{
"city": "city1",
"userId": 1,
"name": "Andrew"
},
{
"city": "city2",
"userId": 2,
"name": "Jessica"
}
]
}
}
],
[
{
"data": {
"legid": 2,
"name": "A380",
"destlist": [
{
"city": "city1",
"userId": 2,
"name": "Jessica"
}
]
}
}
]
]
需要有关如何执行此操作的建议。
如果您可以使用async / await,则更容易想象和实现这样的可读性更高的解决方案
Promise.all(flights.map(async flight => {
const destlist = flight.data.destlist
const updatedDestList = await Promise.all(destlist.map(async dest => {
const user = await getUser(dest.userId)
dest.name = user.name
return dest
}))
flight.destlist = updatedDestList
return flight
}))
完整的工作示例
const flights = [ { data: { legid: 1, name: "A380", destlist: [ { city: "city1", userId: 1 }, { city: "city2", userId: 2 } ] } }, { data: { legid: 2, name: "A380", destlist: [ { city: "city1", userId: 2 } ] } } ]; const users = [ { id: 1, name: "Andrew", schoolId: 101 }, { id: 2, name: "Jessica", schoolId: 999 } ]; const getUser = id => { return new Promise((resolve, reject) => { const user = users.find(user => user.id === id); if (user) { setTimeout(() => resolve(user), 1000); } else { setTimeout(() => reject(`Unable to find user with id of ${id}.`), 1000); } }); }; Promise.all(flights.map(async flight => { const destlist = flight.data.destlist const updatedDestList = await Promise.all(destlist.map(async dest => { const user = await getUser(dest.userId) dest.name = user.name return dest })) flight.destlist = updatedDestList return flight })) .then(function(data) { prettyJSON(data); }) function prettyJSON(obj) { console.log(JSON.stringify(obj, null, 2)); }
由于getUser
函数是异步执行的,因此应在数据完成后返回数据。 使用async/await
:
return Promise.all(
flt.data.destlist.map(async function (item) {
await getUser(item.userId)
.then(us => (item.name = us.name))
.catch(err => console.log(err));
return flt;
}),
);
或者,如果您不熟悉async/await
,则可以直接返回getUser
调用:
Promise.all(
flights.map(function (flt) {
return Promise.all(
flt.data.destlist.map(function (item) {
return getUser(item.userId)
.then(us => {
item.name = us.name;
return flt;
})
.catch(err => console.log(err));
}),
);
}),
).then(function (data) {
prettyJSON(data);
});
这样flt.data.destlist.map
返回一个Promise
数组,因此Promise.all
将等待。
另外,不需要外部的prettyJSON
,这很令人困惑。
由于您不返回Promise,而是返回flt
Promise.all
值,因此不会等到数据加载Promise.all
。
getUser(item.userId)
.then(us => (item.name = us.name))
.catch(err => console.log(err));
return flt;
将其设为return getUser(...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.