2012-09-18 23 views
9

Duplicar posibles:
Coordinating parallel execution in node.jsasincrónica llama rizo interior

En primer lugar, las manos en pseudo-código:

forEach(arrayelements) { 
    asyncQueryFunction(function(qres) { 
    //work with query results. 
    }); 
} 
// finally, AFTER all callbacks did return: 
res.render("myview"); 

cómo hacerlo?

Si eso no fuera lo suficientemente claro, me explico:

tengo que hacer una serie de consultas "actualización" (en mongodb, a través de la mangosta), de enlace a través de una lista de identificadores de documentos. Para cada identificación en mi matriz llamaré a una función asíncrona que devolverá los resultados de la consulta (en realidad, no necesito hacer nada con ellos).

Sé que tengo que usar .forEach() bucle de javascript, pero ¿cómo puedo ejecutar mi devolución de llamada "final" solo cuando TODAS mis consultas asincrónicas terminaron?

Ya estoy usando la excelente biblioteca asincrónica (https://github.com/caolan/async) para realizar este tipo de tareas cuando tengo que ejecutar una serie de tareas "limitadas". Pero no creo que pueda pasarle una serie de funciones diferentes.

¿Lo puedo?

+0

Este es un método: http://stackoverflow.com/questions/4631774/coordin ating-parallel-execution-in-node-js/4631909 # 4631909 – slebetman

+0

puede usar una biblioteca de control de flujo asincrónico, "async" es la más popular (https://github.com/caolan/async) –

Respuesta

9

patrón muy sencilla es utilizar 'consecutivo contador de tareas:

var numRunningQueries = 0 
forEach(arrayelements) { 
    ++numRunningQueries; 
    asyncQueryFunction(function(qres) { 
    //work with query results. 
    --numRunningQueries; 
    if (numRunningQueries === 0) { 
     // finally, AFTER all callbacks did return: 
     res.render("myview"); 
    } 
    }); 
} 

o, alternativamente, el uso de una biblioteca de ayuda asíncrono tal como Async.js

+0

Digamos que tenemos este bloque de código en alguna solicitud mientras se procesa la función asíncrona, digamos que recibimos una solicitud más, en ese caso var numRunningQueries no se sobrescribirá a 0? I – bana

+0

siempre se incrementa antes de la llamada y disminuye al finalizar. JS en el nodo es de un solo hilo, no puede haber condición de carrera aquí –

+0

Pero las funciones aync se ejecutan en un hilo separado ¿Así que estaba pensando como lo que sucede cuando hemos terminado con la matriz pero la función aysnc aún está procesando y más es un local variable, así que creo que conservará su valor. Estoy pensando en las cosas, supongo. – bana

2

Si entiendo correctamente, asyncQueryFunction es siempre el mismo, ya que está aplicando la misma actualización a cada documento.

utilizo un método de ayuda a devolver la llamada después de guardar (sólo cambio para la actualización) varios documentos mangosta (convertido de CoffeeScript, por lo que no puede ser perfecto):

function saveAll(docs, callback) { 

    // a count for completed operations, and save all errors 
    var count = 0 
    , errors = []; 

    if (docs.length === 0) { 
    return callback(); 
    } else { 
    for (var i = 0; i < docs.length; i++) { 

     // instead of save, do an update, or asyncQueryFunction 
     docs[i].save(function(err) { 

     // increase the count in each individual callback 
     count++; 

     // save any errors 
     if (err != null) { 
      errors.push(err); 
     } 

     // once all the individual operations have completed, 
     // callback, including any errors 
     if (count === docs.length) { 
      return callback(errors); 
     } 
     }); 
    } 
    } 
}; 

saveAll(arrayElements, function(errors) { 
    // finally, AFTER all callbacks did return: 
    res.render("myview"); 
} 
Cuestiones relacionadas