node_redis:在forEach中使用client.multi

时间:2012-04-29 17:45:18

标签: node.js redis node-redis

我有以下代码可以检索设备列表并获取每个设备的状态和标签:

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,但是当所有循环都完成后,它就是空的。

1 个答案:

答案 0 :(得分: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这样的异步库提供了帮助方法,可以更容易地执行这样的并行异步循环。