Async ожидает выполнения функции

Я пытаюсь отправить SMS для функции. Но проблема в том, что функция занимает около 10-15 секунд, чтобы закончить (так как мы делаем кучу вещей с помощью PhantomJS).

_.each(users, function(userData){ // This does not work since i need to wait for 15 seconds
  smsFree.sendSMSFree(userData, productUrl);
});

Я даже пытался использовать setTimeout, но это тоже не совсем сработало.

Я нахожусь в NodeJS. Как я могу использовать Async или другую библиотеку для решения моей проблемы?

Я хочу подождать 15 секунд, а затем перейти ко второму объекту. Не знаете, как это достигается. (Async.serial?)

  • R

Ответ 1

Вы должны использовать шаблон обещания с Q, Ваша функция должна вернуть обещание, и все будет проще:

Q.all(users.map(user => smsFree.sendSMSFree(userData, productUrl)))
       .then(() => {
           // Do stuff once every SMS has been successfully sent!
       }); 

Или стандартный Promise:

Promise.all(users.map(user => smsFree.sendSMSFree(userData, productUrl)))
       .then(() => {
           // Do stuff once every SMS has been successfully sent!
       }); 

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

Ответ 2

Быстрое и грязное решение, которое может работать для вас:

var n = 0;
_.each(users, function (userData) {
  setTimeout(function () {
    smsFree.sendSMSFree(userData, productUrl);
  }, 15000 * n++;
});

Он выполняет функции для каждой итерации с интервалами 15000 миллисекунд (15 секунд) между ними. Это единственный способ сделать это , если sendSMSFree не выполняет обратный вызов или не дает обещание.

Если он вернет обещание (что может быть, вы не объяснили, как эта функция работает в вашем вопросе), и вы хотите запустить их все одновременно, но подождите, пока все они закончите - см. ответ на Матиас Фидемайзер.

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

Если функция выполняет обратный вызов, вы можете использовать async.series.

Нет смысла подробно объяснять это, потому что мы даже не знаем, вернёт ли он обещание или вообще выполняет обратный вызов - это все предположения. Вы можете увидеть другие ответы, объясняющие, как promises и обратные вызовы работают, если вам интересно:

Вкратце:

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

Если он возвращает обещание - вы можете использовать Q или Bluebird для управления потоком.

Если требуется обратный вызов, вы можете использовать async для управления потоком.