Асинхронное ожидание функции
Я пытаюсь отправить смс для функции. Но проблема в том, что для завершения функции требуется около 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?)
- р
2 ответа
Вы должны использовать шаблон обещания с 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!
});
Если ваша функция не использует шаблон обещания, вы можете либо обернуть его, чтобы использовать весь шаблон, либо вы застрянете с точки зрения реализации асинхронных продолжений...
Быстрое и грязное решение, которое может работать на вас:
var n = 0;
_.each(users, function (userData) {
setTimeout(function () {
smsFree.sendSMSFree(userData, productUrl);
}, 15000 * n++;
});
Он запускает функции для каждой итерации с интервалами 15000 миллисекунд (15 секунд) между ними. Это единственный способ сделать это, если только sendSMSFree
либо принимает обратный вызов, либо возвращает обещание.
Если он возвращает обещание (что, возможно, вы не объяснили, как эта функция работает в вашем вопросе), и вы хотите запустить их все одновременно, но подождите, пока все они не завершатся - см. Ответ Matías Fidemraizer.
Если вы хотите запустить их последовательно, то есть запустить новый сразу после завершения предыдущего, тогда это будет сложнее. Если вы хотите добавить 15-секундную задержку после того, как предыдущая закончилась до начала следующей, она будет еще более сложной.
Если функция принимает обратный вызов, вы можете использовать async.series.
Нет смысла объяснять это подробно, так как мы даже не знаем, возвращает ли он обещание или вообще принимает обратный вызов - это все домыслы. Вы можете увидеть другие ответы, которые объясняют, как работают обещания и обратные вызовы, если вы заинтересованы:
- Подробное объяснение о том, как использовать обратные вызовы и обещания
- Объяснение того, как использовать обещания в сложных обработчиках запросов
- Объяснение того, что на самом деле является обещанием, на примере запросов AJAX
- Объяснение обратных вызовов, обещаний и способов доступа к данным, возвращаемым асинхронно
В итоге:
Если функция, которую вы вызываете в цикле, не возвращает обещание и не принимает обратный вызов - тогда вы можете только добавить таймауты, чтобы задержать их.
Если он возвращает обещание - вы можете использовать Q или Bluebird для управления потоком.
Если требуется обратный вызов - вы можете использовать async для управления потоком.