Katie
Katie

Reputation: 48198

Socket IO Client receiving object DIFFERENT from what Server sent

I am sending an object from my server side to my client side, and the object that the client gets is totally different than the object I send. Here's what I mean:


Code

Server side code:

//Basic setup for the example
var res={};
res.models=[];
res.models[0]={};

//The OLD (wrong) value
res.models[0]['id']="b4fd12f1-61ca-4445-b916-62617f1c0a78";

//The NEW (correct) value
res.models[0]['id']="fb8f83e2-e157-4e1e-8315-8e5f03b44691";

//Output what the id is, this is always the correct id!
console.log("res.models[0]['id']: ",res.models[0]['id']);
socket.emit("updateRealSeatSelect", res);

Client side code:

socket.on("updateRealSeatSelect", function(data){
    //Output the id when we get the object. This is always wrong!
    console.log("res.models[0]['id']: "+data.models[0]['id']);
});

The output is the problem. Here's what I get:


Output

Server Side Output: (Correct)

res.models[0]['id']:  fb8f83e2-e157-4e1e-8315-8e5f03b44691

Client Side Output: (Wrong! Why is it different??)

res.models[0]['id']: b4fd12f1-61ca-4445-b916-62617f1c0a78

I have double triple quadruple checked that the server is sending the correct object with the correct id. When the client gets the object, the object is different and has the wrong id! How can this happen?


Misc

Attempts:

Versions:

Upvotes: 3

Views: 417

Answers (1)

rsp
rsp

Reputation: 111258

Here is what I think really happens, even though it is not demonstrated in your code example.

Your object's ID looks like UUID which may suggest Cassandra. Even if it's not Cassandra it's probably some database and thus that object is retrieved asynchronously, but you return the response before the object is actually retrieved and you also keep the object in a global variable or in an outer scope that is shared between the invocations of socket.emit().

I also expect that the first socket.emit() after you restart your server returns no object at all and all subsequent responses get the previous one.

So this is not like this:

//The OLD (wrong) value
res.models[0]['id']="b4fd12f1-61ca-4445-b916-62617f1c0a78";

//The NEW (correct) value
res.models[0]['id']="fb8f83e2-e157-4e1e-8315-8e5f03b44691";

socket.emit("updateRealSeatSelect", res);

But more like this:

database.getObject(function (data, res) {
    if (err) {
        // handle error
    } else {
        res = data;
    }
});
socket.emit("updateRealSeatSelect", res);

roughly speaking. Of course it's just speculation because you didn't provide an example that would let us reproduce the problem and you didn't explain the most relevant parts of your code either.

If you get the data asynchronously using callbacks or promises then make sure that you don't try to emit it to the socket before you actually have it.

Also, always use:

'use strict';

at the beginning of your code to make sure that you don't implicitly declare global variables.

And read about concurrency in JavaScript - callbacks, continuation passing style, promises, async functions.

You may have more luck using async function than traditional callbacks and promise handling, so instead of something like this using callbacks:

getFromDatabase(function (err, data) {
    if (err) {
        // handle error
    } else {
        socket.emit('data', data);
    }
});

or something like this using promises:

getFromDatabase().then(function (data) {
    socket.emit('data', data);
}).catch(function (err) {
    // handle error
});

you would write something like:

try {
    socket.emit('data', await getFromDatabase());
} catch (err) {
    // handle error
}

which may be more clear to follow the control flow.

Upvotes: 1

Related Questions