JavaScript, node.js等待socket.on响应后再继续执行

4

我需要在客户端获取服务器上的信息。因此,在服务器端,当客户端首次连接时,会得到以下内容:

socket.on('adduser', function(username){
    // misc code, where i set num_player and whatnot
    socket.emit('confirmauth', socket.id, socket.num_player, function(data){
         console.log(data)
    });
    // code
}

在客户端,我得到了这个:

var current_player;
socket.on('confirmauth', function(id, username, num, callback) {

    current_player = new Player(username,id, num);

    console.log(current_player.id); // works
    console.log(current_player.num); //works
    callback('ok i got it');
});

console.log(current_player.id); //undefined
console.log(current_player.num); //undefined

我的问题是,在socket.on之外,player未定义。似乎javascript在继续执行之前不等待socket.on检索数据。

我尝试将socket.on包装在$.when done中,但它不起作用。我尝试过回调,但我认为我可能没有很好地理解它应该如何工作。所以如果你们中的任何人愿意帮助我,我将非常感激。

谢谢你们的答复。

3个回答

5

如果您试图将current_player变量放在on回调之外以尝试return它,则替代方法是使您自己的函数接收回调。

function getPlayer(onDone){
    socket.on('confirmauth', function(id, username, num, callback) {
        var current_player = new Player(username,id, num);
        onDone(current_player);
    });
}

相比于执行

var player = getPlayer();
//...

你需要做的是

getPlayer(function(player){ 
    //...
});

在Javascript中,“回调函数”的使用有点让人困扰,但直到每个人开始使用生成器之前,这就是生活。


这就是为什么 Node.js 存在 Nibble 的原因。 - Luis Masuelli
@LuisMasuelli:我找不到任何有关Node的“nibble”库的提及。如果你指的是“nimble”,那不是我想要的,因为它仍然强制你使用库来控制流程,而不是使用现有的JS功能,如while循环或try-catch。请参见此处 - hugomg
也许是名字写错了,让我再检查一下……是的,你说得对。无论如何它都很糟糕,但这就是异步编程的限制。 - Luis Masuelli
在getPlayer(function(player)中,我如何让其他代码都可以访问player? - user3597823
@user3597823:什么叫做“到处都是”?基本上,这个想法就是所有访问玩家的代码(由//...表示)都需要移动到回调函数内部。如果player是某种全局变量,你也可以从回调函数内初始化它,但是你需要确保在初始化之后再开始运行使用全局变量的代码:getPlayer(function(p){ player = p; startGame(); }) - hugomg

0
所有这些操作都是异步的,因此最好尽可能避免使用全局变量和状态。
话虽如此,您可以将新创建的Player对象传递给回调函数,让它去处理 - 例如注册玩家等方式进行传输。
callback(current_player)

然后,您可以将其放入全局可用的对象中,例如如果您正在使用Backbone或在服务器端跟踪当前用户。


0
这是因为socket.on在执行回调时运行,并且是在回调中设置玩家。然而,在调用socket.on之后,您尝试读取玩家,但由于未调用回调,因此未设置玩家。请记住,您正在处理异步编程。尝试使用nibble在回调之后链接该代码。
记住:socket.on和许多其他套接字处理程序 - 甚至许多其他事件处理程序(例如jquery)- 不等待事件发生,因此您必须考虑异步。
以这个例子为例:
  1. 当套接字正在连接时(例如,客户端位于Tor后面,连接需要3秒钟),您调用socket.onsocket.on分配事件处理程序(这是它所做的唯一事情,因为它适用于11个或更多事件,以相同的方式工作)。
  2. 您访问玩家。
但是,第1点不需要3秒钟,因为它只是一个赋值 - 连接需要3秒钟才能建立。在这种意义上,您有一个未定义的(实际上是未分配的)变量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接