2013-12-17 6 views
2

Итак, у меня есть хороший кусок вложенного асинхронного кода, который работает, и все кажется, все в порядке, за исключением тех случаев, когда я добираюсь до конца. моя последняя функция в блоке серии является Foreach: что затем переходит в async.parallelс использованием async правильно (с forEach)

Успел выследить следующий кусок, который не запускается в следующем порядке:

async.forEach(array, function(elem, callback) { 
     async.parallel([ 
      function(callback) { 
       database-call-A(elem, unction(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      }, 
      function(callback) { 
       database-call-B(elem, function(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      } 
     ]); // end async.parallel 

     // if forEach needs a callback after every iteration (which I think it does?) 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); // both parallel functions have run, call back forEach 

}); // end forEach 

console.log("Donions - prints when finished"); 

Когда я тестировал этот код бросая заявления о печати повсюду, я заметил, что «PRINTS N TIMES ...» выполнялось N раз, затем я получил «Дотации ...» и ТОГДА я что-то сделал(); и другие вещи(); начал получать вызов в моем async.parallel.

Почему мой forEach выполняет итерацию, не дожидаясь обратных вызовов от async.parallel?

ответ

3

Во-первых, нет async.forEach, но есть функция async.each. Функция async.parallel будет выполнять все задачи одновременно, а затем выполнить обратный вызов, если она была определена.

В вашем источнике функция callback будет выполнена, как только будет выполнен async.parallel, а не после того, как все его функции вернутся. Я предлагаю вам прочитать documentation.

Если вы хотите, чтобы выполнить callback после всех параллельных функций были названы обратные вызовы, вы должны пройти forEach «обратного вызова s к функции async.parallel в качестве второго параметра, после множества функций. Кроме того, вы должны, вероятно, передавать обратные вызовы как на databaseCallA, так и на databaseCallB, тем самым заставляя их вызывать свои обратные вызовы, когда они заканчиваются, поэтому они не выполняются преждевременно.

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      databaseCallA(cb); 
      // if you have called the cb here, the `async.parallel` function would "think" that the databaseCallA has finished, even though it may not have started yet. 
     }, 
     function(cb) { 
      databaseCallB(cb): 
     } 
    ], callback); 
}); 

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

Пункт асинхронных вызовов заключается в том, чтобы освободить ресурсы для других заданий в ожидании завершения вашей работы - ваш код продолжит выполнение, но вы можете использовать обратные вызовы или уведомления о событиях, чтобы уведомить других о ваших работа async завершена.

EDIT

Чтобы выполнить что-то после того, как все параллельные вызовы закончили:

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      // I use the setTimeout function to intentionally 
      // delay the response 
      setTimeout(function() { 
       // the first cb parameter is error, the second is result 
       // in case there was no error 
       cb(undefined, 'a'); 
      }, 500); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'b'); 
      }, 300); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'c'); 
      }, 800); 
     } 
    ], function(err, results) { 
     // this will be executed only after all three cb's are executed. In 
     // this case, after about 800ms. The results variable will be an 
     // array containing the resuts passed to each cb. In this case it 
     // will be ['a', 'b', 'c']. 

     // you could call the main callback here 
     callback(); 
    }); 
}, function(err) { 
    // this callback will be executed either after everything was done, 
    // or if an error has occurred. 
    if (err) { 
     handleError(err); 
     return; 
    } 

    // this should be executed after all `each` and `parallel` calls 
    // have finished. In this case, it should also be after about 800ms 
    // from the start, since everything was executed in parallel 
    console.log('finished'); 

    // now you are sure everything was done, do something afterwards 
    after(); 
}); 

// this will be executed immediately so don't put anything here 
// that depends on the outcome of the async calls above 
console.log('test'); 
+0

Вы правы! Я упростил здесь слишком много, проверьте обновление для получения дополнительной информации (мои вызовы db только возвращаются, когда они возвращаются, так что мы хороши на этом фронте). Я почти уверен, что каждый из них является функцией, рассматривающей ее запуск на моем компьютер, но я задаюсь вопросом, почему я никогда не могу найти его в API - посмотрим, все ли что-нибудь сделают .. – gadu

+0

так что же ваша проблема? – jeremija

+0

именно то, что я описал, у меня есть код ПОСЛЕ мой параллельный запуск перед моей параллелью - так что мой код застревает, так как он не будет возвращаться из forEach, потому что эти обратные вызовы уже произошли. – gadu

0

Я не уверен, что для этого ответа, но в соответствии с асинхронным документацией, я думаю, что вы должны сделать это:

async.forEach(array, function(elem, callback) { 
    async.parallel([ 
     function(callback) { 
      database-call-A(); 
      callback(); 
     }, 
     function(callback) { 
      database-call-B(): 
      callback(); // callback for second parallel function 
     } 
    ], function(err,result) { 
     // this code is executed when paralles functions ends 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); 
    }); // end async.parallel 

}); // end forEach 

Отношения.

+0

Вызов базы данных (должен быть) async, и в этой ситуации ваши обратные вызовы будут выполняться до того, как вызовы базы данных действительно сделают некоторую работу. – jeremija

Смежные вопросы