Как установить новые свойства или нажать на массив с асинхронной и ждать с помощью функции обратного вызова? - PullRequest
0 голосов
/ 03 июля 2018

Это мой скрипт, я не знаю, почему, когда я использую asysc, ожидаю с rawCollection, когда я получаю данные внутри цикла, а затем я устанавливаю новые свойства (poTmp) внутри, я получаю данные, но после того, как я устанавливаю новые свойства, я утешаю их снаружи не установить новую опору, почему?

let items = await Items.rawCollection()
    .aggregate([
      {
        $match: match,
      },
    ])
    .toArray()

  let data = items
  data.forEach(async item => {
    let po = await PurchaseOrderDetails.rawCollection()
      .aggregate([
        {
          $match: {
            itemId: item._id,
            tranDate: { $lte: tDate },
          },
        },
        {
          $group: {
            _id: '$itemId',
            itemDoc: { $last: item },
            onHandPO: { $sum: '$qtyBase' },
          },
        },
        {
          $group: {
            _id: '$itemId',
            itemDoc: { $last: '$itemDoc' },
            lastOnHandPO: { $last: '$onHandPO' },
          },
        },
      ])
      .toArray()
    //==================
    //set new properties
    //==================
    item.poTmp = po[0]

  })
  console.log(data)
  return data

1 Ответ

0 голосов
/ 04 июля 2018

Проблема здесь:

data.forEach(async item => {

Асинхронные функции сразу возвращают обещания при вызове, поэтому forEach завершает работу и переходит к строке console.log.

Асинхронная работа, делегированная асинхронным функциям, еще не завершена, поэтому данные еще не изменены.

Поскольку кажется, что вы уже находитесь в асинхронной функции (поскольку вы использовали await выше в коде), вы можете дождаться разрешения всех обещаний с помощью await и Promise.all

Promise.all ожидает массив обещаний, поэтому вместо forEach мы можем использовать map для создания массива обещаний

await Promise.all( data.map(aysnc item => { ...

Как и forEach, map будет перебирать все элементы и запускать данную функцию. В отличие от forEach, map вернет массив с результатами этих функций, и, учитывая, что они являются асинхронными функциями, каждая из них вернет обещание.

Теперь мы используем Promise.all, чтобы создать одно обещание, которое будет выполнено после завершения каждой из асинхронных функций. И мы используем await, чтобы заставить функцию приостановиться до разрешения этого нового обещания.

Приостановка функции с помощью await означает, что console.log не запустится до тех пор, пока не завершится каждая из этих асинхронных функций, т. Е. При запуске будут правильные данные.

...