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,有 2 个键:“ID:status”、“ID:label”

h.respond 是一个发送 http 响应的辅助方法。

我可以看到每个循环都将新数据添加到 jsonObj 中,但是当所有循环完成时,它是空的。

4

1 回答 1

2

代码异步运行,并且在任何 Redis 调用实际完成之前计数到 devices.length(在继续之前它不会等待回调 frommulti返回)。将您的支票移入回调将防止这种情况发生。

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 回答