1

デバイスのリストを取得し、それぞれのステータスとラベルを取得する次のコードがあります。

app.get('/test', function(req, res){
  db.smembers("devices", function(err1, devices){
    var jsonObj = {};
    if(!err1) {
       var i = 0;
       devices.forEach(function(id){
          db.multi([
             ["get", id + ":label"],
             ["get", id + ":status"],
          ]).exec(function (err, replies) {
             jsonObj[id] = {"label":replies[0], "status":replies[1]};
             console.log(jsonObj);     // stuff is added on each loop
          });

          i = i + 1;
          if(i == devices.length){  
             console.log(jsonObj);     // jsonObj is {}     
             h.respond(res, jsonObj);
          }
       });
    } else {
       h.respond(res, { "error" : err1 });
    }
  });
});

devices は ID のリストです。各 ID には、「ID:status」、「ID:label」の 2 つのキーがあります。

h.respond は、http 応答を送信するヘルパー メソッドです。

各ループで新しいデータが jsonObj に追加されているのがわかりますが、すべてのループが完了すると空になります。

4

1 に答える 1

2

コードは非同期で実行され、Redis 呼び出しが実際に完了する前に devices.length までカウントされます (multi続行する前に からのコールバックが返されるのを待ちません)。チェックをコールバックに移動すると、これを防ぐことができます。

app.get('/test', function(req, res){
  db.smembers("devices", function(err1, devices){
    var jsonObj = {};
    if(!err1) {
       var i = 0;
       devices.forEach(function(id){
          db.multi([
             ["get", id + ":label"],
             ["get", id + ":status"],
          ]).exec(function (err, replies) {
             jsonObj[id] = {"label":replies[0], "status":replies[1]};
             console.log(jsonObj);     // stuff is added on each loop
             i = i + 1;
             if(i == devices.length){  
                console.log(jsonObj);     // jsonObj is {}     
                h.respond(res, jsonObj);
             }
          });


       });
    } else {
       h.respond(res, { "error" : err1 });
    }
  });
});

おそらく、このコードを別の関数に移動する方が理にかなっているでしょうが、うまくいけば、アイデアが得られることを願っています. のような非同期ライブラリasyncは、このような並列非同期ループをより簡単に実行できるようにするヘルパー メソッドを提供します。

于 2012-04-29T17:54:55.817 に答える