我放弃了这一点。愿一些聪明的stackoverflow僧侣请修复我的错误吗?
代码是自我解释。客户端发送房间名称,服务器执行redis查找并将有效房间推送到阵列。添加所有房间后,应将列表发送给客户端。
问题是基于闭包,异步等。我理解这个问题,但无法获得解决方法,因为数组需要保留在函数内部。棘手。
代码:
function roomList(socket){
var roomlist = [], rooms = getRooms(), p = /pChannel_/;
redis.select(7, function(err,res){
for (var k in rooms){
if(rooms[k] != '' && p.test(rooms[k])){
var key = 'channel:'+rooms[k];
redis.hgetall(key, function (err, reply) {
if(reply){
var c = io.sockets.manager.rooms[rooms[k]];
roomlist.push( Array(reply['name'],c.length,reply['icon']) );
}
else { console.log('nothing found'); }
});
}
}
// here be dragons
console.log(roomlist);
socket.emit('roomList', roomlist);
});
}
感谢。
答案 0 :(得分:1)
看起来像async.map的作业:
function roomList(socket){
var rooms = getRooms(), p = /pChannel_/;
redis.select(7, function(err, res) {
async.map(rooms, function(room, callback) {
if (room === '' || ! p.test(room))
return callback(null, null);
var key = 'channel:' + room;
var c = io.sockets.manager.rooms[room];
redis.hgetall(key, function (err, reply) {
if (err)
callback(err); // propagate Redis errors to final callback, don't know
// if you want that or not; use 'callback(null)' if not.
else
if (reply)
callback(err, Array(reply.name, c.length, reply.icon) );
else
callback(err, null);
});
}, function(err, roomlist) {
if (err)
// handle Redis errors...
// filter 'null' entries from roomlist
roomlist = roomlist.filter(function(room) { return room !== null });
console.log(roomlist);
socket.emit('roomList', roomlist);
});
});
}
(未测试的)
答案 1 :(得分:0)
如果您只是想在发出响应之前等待房间列表完全构建(看起来非常合理),并且假设Q可用,那么您应该只需要一些额外的Q魔术线和一个闭包 - 在内部代码周围形成包装器,以保持对for循环的每次传递延迟的Q的可靠引用。
function roomList(socket) {
redis.select(7, function(err, res) {
var list = [],
rooms = getRooms(),
p = /pChannel_/,
promises = [];
for(var k in rooms) {
if(rooms[k] != '' && p.test(rooms[k])) {
(function(dfrd) {
promises.push(dfrd.promise);
var key = 'channel:' + rooms[k];
redis.hgetall(key, function(err, reply) {
if(reply) {
var c = io.sockets.manager.rooms[rooms[k]];
list.push( [reply['name'], c.length, reply['icon']] );
}
else {
console.log('nothing found');
}
dfrd.resolve();
});
})(Q.defer());
}
}
Q.all(promises).then(function() {
console.log(list);
socket.emit('roomList', list);
});
});
}
答案 2 :(得分:0)
在初始代码中,有两个问题:
使用Javascript,闭包范围是功能级别,而不是块级别。必须引入一个函数来定义一个合适的闭包。在这里,可以使用简单的forEach。
在收到Redis的回复后,不会运行最后一步(即发出)。它必须在循环中调用。为了实现它,需要对项目进行计数,以便内部回调可以测试过程是否完成。
所以这是另一个版本:
function roomList(socket){
var roomlist = [], rooms = getRooms(), p = /pChannel_/;
redis.select(7, function(err,res){
var count = rooms.length
rooms.forEach( function(r) {
if( r != '' && p.test(r) ) {
var key = 'channel:'+r
redis.hgetall(key, function (err, reply) {
if(reply) {
var c = io.sockets.manager.rooms[r];
roomlist.push( Array(reply['name'],c.length,reply['icon']) );
} else {
console.log('nothing found');
}
if ( --count <= 0 ) {
// here be dragons
console.log(roomlist);
socket.emit('roomList', roomlist);
}
});
} else --count;
});
});
}