我正在学习JavaScript和Node.js,我目前正在制作一个Node.js应用来管理我的飞利浦色调灯。我正在努力应对异步和回调。
首先让我解释一下我想要实现的目标。我有一个功能,可以获得" id"在我的所有灯光中,named getLightsId
:
function getLightsId(callback){
args ={
path:{"username":"username"}
};
client.registerMethod("getLightState", "bridge_adress/api/${username}/lights/", "GET");
client.methods.getLightState(args, function(data,response){
var id = [];
for(key in data){
id.push(key);
}
callback(id);
});
}
然后我有一个函数getLightState
来获取由其id确定的特定灯的状态:
function getLightState(id, callback){
args ={
path:{"username":"username", "id":id}
};
client.registerMethod("getLightState", "http://bridge_address/api/${username}/lights/${id}", "GET");
client.methods.getLightState(args, function(data,response){
callback(data);
});
}
最后我有一个函数initLightsState
,它将对象中所有灯光的状态发送给我的客户端。准备好看丑陋的代码;它很脏,但嘿,它有效。
function initLightsState(callback){
getLightsId(function(idArray) {
var lightsState = new Object();
idArray.forEach(function(id) {
setInterval(function(){getLightState(id, function(state) {
lightsState[id] = state;
});},500);
});
callback(lightsState);
io.sockets.on('connection', function (socket) {
setInterval(function(){
socket.emit('updateLightsState', lightsState);
},500);
});
});
}
我必须将setInterval()
放到我的getLightState
函数中,否则它总是向我发送具有相同数据的相同对象。然后我也向我的客户发出setInterval()
我的对象。
问题在于它显然是在向我的客户发送垃圾邮件状态。它有效,但它远非最简洁的方法。
我想要做的是将服务器端以前的状态与当前的状态进行比较,并且只有在不同的情况下将其发送给客户端。
但是我仍然坚持使用回调和一切,并且无法让它发挥作用。有人可以告诉我最简单的方法吗?
我认为我应该使用异步和深度相等的模块,但我真的迷失了......
答案 0 :(得分:0)
我终于使用https://github.com/caolan/async
中的async.waterfall找到了解决方案我不确定这是否是最好的方法,但效果很好: 我终于找到了解决方案,我不确定它是否有效,但它有效,我使用了async.waterfall,感谢Floby的帮助!
// initialise previousState
var previousState = "Original";
io.sockets.on('connection', function (socket) {
setInterval(function(){
async.waterfall([
function getLightsId(callback) {
args = {
path: {
"username": "username"
}
};
client.registerMethod("getLightState", "http://bridheip/api/${username}/lights/", "GET");
client.methods.getLightState(args, function (data, response) {
var ids = [];
for (key in data) {
ids.push(key);
}
callback(null, ids);
});
},
function getLightsState(ids, callback) {
var lightsState = new Object();
async.reduce(ids, {}, function(lightsState, id, rcallback) {
getLightState(id, function(state) {
lightsState[id] = state;
rcallback(null, lightsState);
});
}, callback);
},
],
function (err, currentState) {
if(JSON.stringify(currentState) !== JSON.stringify(previousState)){
io.sockets.emit('updateLightsState', currentState);
previousState = currentState;
console.log("state changed");
}
});
},1000);
});