Как ждать нескольких асинхронных вызовов из цикла forEach? - PullRequest
0 голосов
/ 13 сентября 2018

Попытка вызова нескольких асинхронных функций, в результате чего получается результат как undefined.

Пытался async.waterfall, однако не удается заставить его работать.

Код:

const pendingData = [];

async.waterfall([
    function (callback) {
      WaitForApproval.find({}, (err,result) => {
        callback(null,result);
      });
    },
    function (result, callback) {
      result.forEach(data => {
        User.findOne({_id: data.uploadedBy}, (err,name) => {
          let total = {
            id: data._id,
            name: name.name,
            subject: data.subject,
            uploadOn: data.uploadedAt
          };
          pendingData.push(total);
        });
      });
      callback(null,'done');
    }
  ], function (err,result) {
    if(result === 'done') {   
      console.log(pendingData); // it is giving empty result.
    }
  });

Как ждать асинхронную функцию?

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Я бы посоветовал вам добавить вызов для callback(null,'done'); немедленно pendingData.push(total);

вы правы, асинхронная природа усложняет вам задачу сейчас, но предположим, что вы использовали Обещания и связали их вместе, чтоизбавил бы вас от многих хлопот.

один раз у меня была похожая проблема асинхронного кода, работающего не по порядку, который я хотел, поэтому я сделал небольшой твик, используя пользовательскую функцию обещания (я исправляю), и вызвал ееorder..such Идея может решить вашу проблему, если вы сможете правильно применить ее к своему коду https://github.com/lalosh/Ideas/blob/master/promiseOrder.js

0 голосов
/ 13 сентября 2018

Проблема, с которой вы столкнулись, заключается в том, что вы являетесь асинхронными функциями в неасинхронном цикле forEach.

У вас есть несколько вариантов здесь:

  1. Сделать mongoDBвызвать рекурсивно - обернуть этот запрос в функцию, которая вызывает себя после его возврата.

  2. Читать о пакетных операциях mongoDB - https://docs.mongodb.com/manual/reference/method/Bulk/

  3. Использовать асинхронно/ await шаблон с каждым вызовом, объявляя функцию обратного вызова в асинхронном водопаде как «async», а затем используя «await» внутри функции для каждого запроса.Из коробки forEach не асинхронный.Если вы все еще хотите использовать forEach, вы можете переписать его как асинхронный (см. Ниже) или использовать обычный цикл for:

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}

** Существуют и другие способы решения этой проблемы, помимо того, что опубликовано здесь, но вот несколько вещей, которые будут работать, если реализованы правильно.

...