【问题标题】:NodeJS + MongoDB ASYNC results appearing lateNodeJS + MongoDB ASYNC 结果出现较晚
【发布时间】:2013-08-14 06:02:12
【问题描述】:

我有一个简单的函数,它返回通道中已连接用户的列表,我在初始阶段使用一个简单的数组,但是知道,我想从 mongodb 数据库中检索一些用户详细信息并将其添加到那个数组。

我遇到的问题是返回结果为空,稍后我可以在控制台日志中清楚地看到,这是因为查询运行较晚并且返回在返回结果之前运行。

我知道这是因为异步函数,我已经尝试过 Q 和其他函数,但我就是无法让它工作。 :(

//GET USERS FOR SPECIFIED ROOM
function get_room_users( room ){

    // create an array to hold all the usernames of the poeple in a specific room
    var roomusers = new Array();        

    // get all the clients in ‘room1′
    var clients = io.sockets.clients( room );

    var i = 0;

    for(var i = 0; i < clients.length; i++) {

        db.users.findOne( { email: clients[i].username }, function(err, userdata) {

            if( err || ! userdata ){

                console.log('no user found');

            } else { 
                console.log("DISPLAYING USER DATA: " + userdata.nickname);
                roomusers[roomusers.length] = userdata.nickname;


                console.log("HERE THE CONSOLE SHOWS ROOMUSERS FILLED IN");
                console.log(roomusers);

                i++;

            }

        });

    }

    console.log("HERE THE ARRAY LOOKS EMPTY BEFORE SENDING BACK");
    console.log(roomusers);

    return roomusers;


}

var users = get_room_users(room1);

console.log("HERE THE ARRAY LOOKS EMPTY!")
console.log(users);

控制台日志结果

HERE THE ARRAY LOOKS EMPTY BEFORE SENDING BACK
[]
HERE THE ARRAY LOOKS EMPTY!
[]
HERE THE CONSOLE SHOWS ROOMUSERS FILLED IN
['user@user.com']

终于解决了: 好的,正如其中一位用户评论的那样,我在考虑同步模式,我在解决 bucle 后更改了 emit 方法,以便在一切完成后发出。请记住,我使用 Q 来创建承诺 :)

//获取指定房间的用户 函数get_room_users(房间){

var the_promises = [];

// create an array to hold all the usernames of the poeple in a specific room
var roomusers = new Array();        

// get all the clients in ‘room1′
var clients = io.sockets.clients( room );

clients.forEach(function (socket) {

    var deferred = Q.defer();

    db.usuarios.findOne( { email: socket.username }, function(err, userdata) {

        if( err || ! userdata ){

            console.log('no user found');
            deferred.reject();

        } else { 
            console.log("DISPLAYING USER DATA: " + socket.username);
            roomusers[roomusers.length] = socket.username;

            console.log("DENTRO DEL BUCLE");
            console.log(roomusers);

            deferred.resolve();

        }

    });

    the_promises.push(deferred.promise);    


});


Q.all(the_promises).done( function(){   
    console.log("ALL THINGS DONE!"); 
    // broadcast to everyone in room 1 the usernames of the clients connected.
    io.sockets.to( room ).emit('updateroomusers', roomusers);   
 } );

}

【问题讨论】:

标签: javascript node.js mongodb asynchronous socket.io


【解决方案1】:

我建议你使用 Q Promises (https://npmjs.org/package/q)。 Promises 是一个非常强大的用于调度异步操作的工具。

【讨论】:

  • 你介意帮我举一个可能的例子吗?我无法让它与 Q 一起使用。我昨天尝试使用 deferred 但也许我做错了什么。
  • 我已经这样做了,但结果相同甚至更糟,我可能肯定做错了什么:
【解决方案2】:

是的,这是在异步环境中使用同步样式的问题。在响应返回之前执行在io.sockets.clients( room ) 之前运行。

以下应该有效:

io.sockets.clients(room).forEach(function (socket) {
    // Your for-loop code
    db.users.findOne( ... );
});

【讨论】:

  • 我试过这个没有运气,代码运行完全一样。 :(
猜你喜欢
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 2020-01-06
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
相关资源
最近更新 更多