1

I need help making my javascript asynchronous because I'm querying from a database with node. I'm using node.js and socket.io. The code works if I use setTimeout() functions, but I want to make my code more reliable so I'm trying to implement callbacks. However, I don't know how to use "socket.on()" properly in callback functions. I think the problem is that I'm nesting socket.on calls and the second "socket.on()" call doesn't execute. Any help would be greatly appreciated, thanks.

/*server side*/
socket.emit(variable1);//not important
socket.emit(variable2);//not important
//code above isn't important, I just wanted to show how data is used from my queries



/*client side*/
var socket = io.connect('123.456.789.123:3000');
var data = " ";//data I need to pass around


   socket1(data, function(){
        socket2(data)
   });


   function socket1(data, callback) {
        socket.on('variable1', function (data)  {
            console.log("1");
            callback();
        }, callback)
    }

    function socket2(data) {
        console.log("2");
        socket.on('variable2', function (data) {
            console.log("3");
        })
    }

The output is "12" and should be "123"

1 Answer 1

3

Think of the asynchronous on function calls as a registration process for registering handlers for when data is received as a push from the server.

function registerVariable1(callback) {

    socket.on('variable1', function (data)  {
        console.log("1");
        callback(data);
    });
}

function registerVariable2(callback) {

    socket.on('variable2', function (data)  {
        console.log("2");
        callback(data);
    });
}

On the server, when you emit data to the clients, use the name of the handler as the first argument, as described here.

socket.emit('variable1', {data: 1});
socket.emit('variable2', {data: 2});

This will send the data down to the correct handler.

With that said, you may be thinking of this wrong. Don't think of each handler as being specific to a single operation. Think of this as registering a listener with the server so that the server can continue to send data back through to that handler. Both registerVariable1 and registerVariable2 only need to be called one time, and then your server can push data back to each handler N times.

To register the handlers, you simply pass in a callback function into each:

registerVariable1(function(data) {
    console.log('This is the first handler');
    console.log(data);
    // do stuff for this handler here...
});

registerVariable2(function(data) {
    console.log('This is the second handler');
    console.log(data);
    // do stuff for this handler here...
});

Now, if the server makes the following three calls:

socket.emit('variable1', {data: 123});
socket.emit('variable2', {data: 24});
socket.emit('variable1', {data: 22});

You might see the following output:

1
This is the first handler
{data: 123}
2
This is the second handler
{data: 24}
1
This is the first handler
{data: 22}

Order may not be guaranteed; however, since you're dealing with the network. But hopefully this helps you see how this works.

Sign up to request clarification or add additional context in comments.

4 Comments

Hey, thanks for the in depth explanation! My server code can only emit once, because it does so after it makes a query from the db. I implemented my code the same way as you specified, and output is being printed, but the methods print out in the wrong order (2,1). Is there a way to make sure registerVariable1() executes and finishes completely before registerVariable2() is called? That's what I'm trying to achieve, and perhaps the server side is the issue, but I can't query more than once so each handler can only have one set of data emitted. Hope that makes sense. Thanks again!
It sounds like your problem isn't server side, it's client side. It sounds like you have all of the data from the database when you're emitting it, so you could just emit it within a JSON object and then deal with that data separately, no?
In other words, socket.emit({varOne: dataForVar1Here, varTwo: dataForVar2Here}); send all the data all at once, is what I'm saying...
Thanks @Mike. The Socket.IO team should use different permalinks in their documentation. What a nightmare. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.