2012-04-29 41 views
1

我有下面的代码应该retrive设备列表,并获得地位和标签为他们每个人:node_redis:使用client.multi内的forEach

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

设备是ID的列表。对于每个ID,有2个键:“ID:status”,“ID:label”

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

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

+0

有类似的问题。良好的问题 – Federico

回答

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这样的异步库提供了帮助器方法,这样可以更容易地完成这样的并行异步循环。

+0

我没有在rigth回调级别,然后,感谢很多现在工作正常! – Luc

+0

很好的发现!我第二次推荐[异步](https://github.com/caolan/async)。我无法推荐这个库,它确实有助于以最小的复杂度来清理这种流量控制。 –