繁体   English   中英

在嵌套循环中处理promise

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM