user3597823
user3597823

Reputation: 55

JavaScript, node.js wait for socket.on response before continuing

I need to get information from the server on the client side. So on the server side I got this when a client first connect:

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
}

and on the client side I got this:

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

my problem is that outside of the socket on, the player is not defined. It seems that javascript doesn't wait for my socket on to retrieve data before carrying on.

I tried to wrap socket.on in a $.when done, but it doesn't work. I tried to do a callback, but I think I may not have understood very well how it is supposed to work. So if one of you is willing to help me, I will be grateful

Thank you for your answers.

Upvotes: 4

Views: 7314

Answers (3)

Gauss156
Gauss156

Reputation: 86

All of these operations are asynchronous, so it's best to avoid global variables and statefulness as much as possible.

That said, have your callback take the newly created Player object to where it needs to go - a register of players, maybe? - and transport it that way.

callback(current_player)

From there, you can put it into a globally available object as you like, for instance if you're using Backbone or have something on the server side keeping track of current users.

Upvotes: 0

hugomg
hugomg

Reputation: 69924

If you are putting the current_player variable outside of the on callback in an attempt to return it, the alternative is to make your own function receive a callback

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

And instead of doing

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

You do

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

It kind of sucks that the "callbackyness" is a bit infectious in Javascript but such is life until everyone starts using Generators instead.

Upvotes: 5

Luis Masuelli
Luis Masuelli

Reputation: 12323

This is since socket.on runs taking a callback, and is in the callback where the player is set. however, after calling socket.on you try to read the player, but it is not set, since the callback was not called. Remember you're dealing with asynchronous programming. Try using nibble to chain that code after the callback.

Remember: socket.on and many other socket handlers -and even many other event handles (e.g. jquery)- DON'T wait to the event to happen, so you must think asynchronously.

Take this example:

  1. You call socket.on while the socket is connecting (The connection takes 3 seconds since, e.g., the client is behind Tor). socket.on assigns the event handler (it's the only thing it does since it works for the 11 or more events it has, in the same way).
  2. You access the player.

But the point 1 does not take 3 seconds since it's just an assignment - the connection is what takes 3 seconds to be established. In that sense, you have an undefined (actually: unassigned) variable.

Upvotes: 0

Related Questions