Запрос в mongoose с вложенным вторым запросом

Здравствует, имеется код для записи в эксель таблицу (библиотека exceljs):

Value.find({ enterpriseId: req.params.id })
        .then((el) => {
          const workbook = new Excel.Workbook();
          const sheet = workbook.addWorksheet('sheet');
          let i = 1;
          const arr = [];
          el.forEach((item) => {
            if (!arr.some((u) => u === item.num)) {
              arr.push(item.num);
            }
          });

          sheet.autoFilter = 'A1:AZ1';
          arr.forEach((u) => {
            el.filter((f) => f.num === u).forEach((value, index) => {
              if (index === 0 && value.proff) {
                Proff767.find({ proff: value.proff }).then((s) => {
                  s.forEach((SIZ) => {
                    sheet.addRow(SIZ);
                  });
                }).catch((e) => next(e));
              }
              value.number = i;
              sheet.addRow(value);
              i += 1;
            });
          });

Проблема в том, что данные из запроса Proff767.find находящиеся в блоке then() приходят после завершения основного цикла и запись в таблицу не происходит, где я ошибся?


Ответы (1 шт):

Автор решения: Ruslan

Проблема заключается в том, что вы работаете с асинхронными операциями в цикле, и метод Proff767.find возвращает ПРОМИС, который выполняется АСИНХРОННО. В результате все промисы, созданные в цикле, выполняются в фоновом режиме, а основной поток кода продолжает выполнение и завершает работу цикла, не дожидаясь результата этих промисов.

Для этого можно использовать async/await вместе с Promise.all.

Value.find({ enterpriseId: req.params.id })
  .then(async (el) => {
    const workbook = new Excel.Workbook();
    const sheet = workbook.addWorksheet('sheet');
    let i = 1;
    const arr = [];
    el.forEach((item) => {
      if (!arr.some((u) => u === item.num)) {
        arr.push(item.num);
      }
    });

    sheet.autoFilter = 'A1:AZ1';
    
    const proffPromises = [];
    
    arr.forEach((u) => {
      const filteredValues = el.filter((f) => f.num === u);
      filteredValues.forEach((value, index) => {
        if (index === 0 && value.proff) {
          const proffPromise = Proff767.find({ proff: value.proff }).then((s) => {
            s.forEach((SIZ) => {
              sheet.addRow(SIZ);
            });
          });
          proffPromises.push(proffPromise);
        }
        value.number = i;
        sheet.addRow(value);
        i += 1;
      });
    });

    // Дождаться выполнения всех асинхронных запросов к базе данных
    await Promise.all(proffPromises);

    // Сохранение Excel файла или дальнейшие действия
  })
  .catch((e) => next(e));
→ Ссылка