para el bucle sobre el evento de código impulsado?

En un almacén de datos de redis tengo una lista de claves, quiero recorrer esa lista de claves y obtener esos valores de redis. El problema es que estoy usando un lenguaje controlado por eventos, javascript a través de node.js

Si javascript fuera procesal podría hacer esto

function getAll(callback) { var list = redis.lrange(lrange('mykey', 0, -1); for ( var i = 0; i < list.length; i+= 1 ) { list[i] = redis.hgetall(list[i]); } callback(list); } 

Pero, no puedo, para eso .. hago esto?

 function getAll(callback) { redis.lrange('mykey', 0, -1, function(err, reply) { // convert reply into messages var list = []; var index = -1; var recurse = function() { if ( index == reply.length ) { callback(list); } else { redis.hgetall(reply[i], function(err, reply) { list.push(reply); index += 1; recurse(); }); } }; recurse() }); }; 

Esto es incorrecto, ya que, en lugar de ejecutar todas las solicitudes a la vez y luego dejar que las devoluciones de llamada se inserten en la lista, estoy forzando una secuencia de llamada secuencial. ¿Qué pasa si hay miles de llaves?

¿Podría hacer esto de alguna manera?

 function getAll(callback) { redis.lrange('mykey', 0, -1, function(err, reply) { // convert reply into messages var list = []; var insert = function(err, reply) { list.push(reply); }; for ( var i = 0; i < reply.length; i += 1 ) { redis.hgetall(reply[i], insert); } ??? how to block until finished ??? callback(list); }); }; 

Declare una variable de objeto antes de enviar sus llamadas dentro del bucle for. Cada llamada puede agregar su resultado al objeto.

A continuación, necesita un código para esperar a que se realicen todas las llamadas. Esto podría ayudarte: https://gist.github.com/464179

Ejemplo:

 function getAll(callback) { var results = []; var b = new Barrier(2, function() { // all complete callback callback(); }, function() { // Aborted callback, not used here }); var list = redis.lrange(lrange('mykey', 0, -1); for ( var i = 0; i < list.length; i+= 1 ) { //dispatch your call call(function(foo){ results.push(foo); b.submit(); }); } } 

Tenga en cuenta que call() debe ser su función de base de datos asíncrona, que ejecuta la callback en el resultado.

??? ¿Como bloquear hasta terminar?

No puedes, no si las llamadas que haces son asíncronas. getAll definir su getAll con la expectativa de que se completará de forma asíncrona y luego getAll a getAll .

No estoy familiarizado con las llamadas de redis que está haciendo, pero el patrón fundamental es:

 function doTheBigThing(param, callbackWhenDone) { asyncCallToGetList(param, function(result) { var list = []; asyncCallToGetNextEntry(result.thingy, receivedNextEntry); function receivedNextEntry(nextResult) { if (nextResult.meansWeAreDone) { callback(list); } else { list.push(nextResult.info); asyncCallToGetNextEntry(result.thingy, receivedNextEntry); } } }); } 

Rompiendo eso

  1. doBigThing (tu getAll ).
  2. Hace la llamada “obtener la lista”, pasando la función para usarla como callback cuando tenemos la lista o el manejador de la lista o lo que sea.
  3. Esa callback define una función, receivedNextEntry , y llama a la función “obtener la siguiente entrada” con cualquier información que se use para recuperar la entrada, y la pasa como una callback.
  4. receivedNextEntry almacena la entrada que recibió y, si se hace, activa la callback principal “todo listo”; Si no, emite la siguiente petición.

Lamento no poder darle una respuesta específica de redis, pero creo que las asignaciones son:

  • doBigThing = getAll
  • asyncCallToGetList = redis.lrange
  • asyncCallToGetNextEntry = redis.hgetall

… pero cuáles son los parámetros que usa con redis.lrange y redis.hgetall me temo que no sé.

Si necesita usar patrones como este a menudo, entonces puede estar interesado en probar la biblioteca async.js . Usando async.js podrías escribir algo como esto:

 function getAll(callback) { redis.lrange('mykey', 0, -1, function(err, reply) { async.concat(reply, redis.hgetall, callback); }); }; 

Lo que básicamente significa “llamar a hgetall en cada elemento en ‘respuesta’, concat todos los resultados y pasar a la callback”.