Async espera una función

Estoy tratando de enviar un SMS para una función. Pero el problema es: la función tarda unos 10-15 segundos en finalizar (ya que hacemos muchas cosas con PhantomJS).

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

Incluso he intentado usar setTimeout pero eso tampoco funcionó.

Estoy en NodeJS. ¿Cómo puedo aprovechar Async o alguna otra biblioteca para resolver mi problema?

Quiero esperar 15 segundos y luego pasar al segundo objeto. No estoy seguro de cómo se logra esto. (Async.serial?)

  • R

Debes usar el patrón de promesa con Q. Tu función debería devolver una promesa y las cosas serán más fáciles:

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

O Promise estándar:

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

Si su función no usa el patrón de promesa , puede envolverlo para usar el patrón completo o quedará atascado en términos de implementar continuaciones asíncronas …

Una solución rápida y sucia que podría funcionar para usted:

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

Ejecuta las funciones para cada iteración con intervalos de 15000 milisegundos (15 segundos) entre ellas. Esta es la única forma en que puede hacerlo a menos que sendSMSFree tome una callback o devuelva una promesa.

Si devuelve una promesa (lo que es posible, no explicó cómo funciona esa función en su pregunta) y desea ejecutarlas todas al mismo tiempo, pero espere hasta que todas hayan finalizado; consulte la respuesta de Matías Fidemraizer.

Si desea ejecutarlos en serie, es decir, ejecutar uno nuevo tan pronto como finalice el anterior, será más complicado. Si desea agregar un retraso de 15 segundos después de que termine el anterior antes de comenzar el siguiente, será aún más complicado.

Si la función recibe una callback, puede usar async.series .

No tiene sentido explicarlo en detalle, ya que ni siquiera sabemos si devuelve o no una promesa o acepta la callback, esto es toda especulación. Puede ver otras respuestas que explican cómo funcionan las promesas y las devoluciones de llamadas si está interesado:

  • Una explicación detallada sobre cómo utilizar devoluciones de llamada y promesas
  • Explicación sobre cómo usar promesas en manejadores de solicitudes complejas
  • Una explicación de lo que realmente es una promesa, en el ejemplo de solicitudes AJAX
  • Una explicación de las devoluciones de llamada, promesas y cómo acceder a los datos devueltos de forma asíncrona

En resumen:

Si la función a la que llama en el bucle no devuelve una promesa ni recibe una callback, entonces solo puede agregar tiempos de espera para retrasarlos.

Si devuelve una promesa, puedes usar Q o Bluebird para controlar el flujo.

Si requiere una callback, puede usar async para controlar el flujo.