2

In einem Redis-Datenspeicher habe ich eine Liste von Schlüsseln, ich möchte über diese Liste von Schlüsseln iterieren und diese Werte von redis erhalten. Der Haken ist, ich bin mit einer ereignisgesteuerte Sprache, javascript über node.jsfür Schleife über ereignisgesteuertem Code?

wenn Javascript Verfahren waren konnte ich dies tue

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); 
} 

Aber ich kann nicht, dafür .. ich das tun?

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() 
    }); 
}; 

Diese Nähte falsch, weil, anstatt alle Anfragen auf einmal ausführen, und dann lassen Rückrufe auf die Liste einzufügen, ich bin eine sequentielle Aufrufsequenz zu erzwingen. Was passiert, wenn es 1000 Schlüssel gibt?

Könnte ich das wie?

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); 
    }); 
}; 
+0

Beide Antworten sind großartig, der Barrier Gist hat den Trick für mich gemacht – Daniel

Antwort

1

Deklarieren Sie eine Objektvariable, bevor Sie Ihre Aufrufe innerhalb der for-Schleife versenden. Jeder Aufruf kann sein Ergebnis dem Objekt hinzufügen.

Sie brauchen dann Code, um auf alle Anrufe warten zu können.Dies könnte Ihnen helfen: https://gist.github.com/464179

Beispiel:

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(); 
     }); 
    } 
} 

Bitte beachten Sie, dass call() sollten Ihre Asynchron Datenbankfunktion sein, die den Rückruf auf Ergebnis führt.

3

??? Wie blockiere ich bis zum Ende ???

Sie können nicht, nicht wenn die Anrufe, die Sie machen, asynchron sind. Sie müssen Ihre getAll mit der Erwartung definieren, dass sie asynchron abgeschlossen wird, und dann ein wenig umwandeln.

Ich bin nicht vertraut mit der redis Sie machen nennt, aber das Grundmuster ist:

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); 
      } 
     } 
    }); 
} 

dass nach unten brechen:

  1. doBigThing (Ihre getAll) genannt wird.
  2. Es führt den "Get the List" -Aufruf, übergibt die Funktion, um als Rückruf zu verwenden, wenn wir das Listen- oder Listen-Handle oder was auch immer haben.
  3. Dieser Callback definiert eine Funktion, receivedNextEntry, und ruft die Funktion "get the next entry" mit der Information auf, die zum Abrufen des Eintrags verwendet wird, und übergibt diese als Rückruf.
  4. receivedNextEntry speichert den Eintrag, den es erhalten hat, und, wenn dies erfolgt ist, feuert den Haupt-Rückruf "all done"; Wenn nicht, gibt es die nächste Anfrage aus.

Leider nicht in der Lage Ihnen eine redis spezifische Antwort zu geben, aber ich denken die Zuordnungen sind:

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

... aber welche Parameter verwendest du mit redis.lrange und redis.hgetall Ich fürchte, ich weiß es nicht.

+0

Danke! Das hilft definitiv! – Daniel

1

Wenn Sie häufig Muster wie diese verwenden müssen, könnten Sie das async.js library ausprobieren. Mit async.js Sie so etwas schreiben könnte:

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

was im Grunde bedeutet „nennen hgetall für jedes Element im‚Antwort‘dann concat alle Ergebnisse und an die Callback übergeben“.