2012-04-29 70 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)。我無法推薦這個庫,它確實有助於以最小的複雜度來清理這種流量控制。 –