spectralbat
spectralbat

Reputation: 407

Correct variable on server gets passed as an incorrect variable to client via socket.io

I am attempting to pass a variable from the server to the client via socket.io. I'm saving data to MongoDB and using Mongoose. The goal is to save some data from the client into the database, then pass the _id of that just-saved document back to the client. Here's what I have so far:

Server

client.on('savesnail', function (data) {
    console.log('save snail: ' + data.name);
    var snail = new Snail(data);
    snail.save(function (err, snail) {
        if (err) {console.log('err: ' + err)} // TODO handle the error
        var snailID = snail._id;
        console.log('saved snail ID ' + snailID);
        client.emit('setSnailID', snailID);
        var conditions = {_id: data.ownerID},
            update = {$set: {newUser: false}}

        User.update(conditions,update,function(err){});
        console.log('user updated');
    });

});

Client

saveSnail: function(snail) {
    // Core stats
    var data = {};
    data.ownerID = ig.game.sessionUserID;
    data.inDb = true;
    data.name = snail.name;
    // etc..

    console.log('saving snail');
    this.socket.emit("savesnail", data);
    this.socket.once('setSnailID', function(snailid) {
        snail.snailID = snailid;
        console.log('snail ID set: ' + snailid);
    }); 
}

In the server console, each 'saved snail ID' appears unique and correct, as it should. However, after it emits to 'setSnailID' and I print the same variable to the client console, the ID turns out to be identical with every emit.

Console output example

As an example let's pretend the _ids are single digit numbers. Right now I am calling saveSnail() on the client four times, once for each of the four snails that are initiated. In the server console I would see:

saved snail ID 1
saved snail ID 2
saved snail ID 3
saved snail ID 4

...but when emitting each _id to the client, in the client console I see:

snail ID set: 1
snail ID set: 1
snail ID set: 1
snail ID set: 1

I should note that if I change this.socket.once in the client to this.socket.on, the client console gets four instances of each ID, so then it starts to print:

snail ID set: 1
snail ID set: 1
snail ID set: 1
snail ID set: 1
snail ID set: 2
snail ID set: 2
snail ID set: 2
snail ID set: 2
// etc

...resulting in 16 lines in total - 4 for each ID

I've only recently started playing around with node.js and think I'm misunderstanding something very basic here. How can I pass the correct, unique _id that MongoDb assigns to each new entry back to the client?

Upvotes: 1

Views: 113

Answers (1)

generalhenry
generalhenry

Reputation: 17319

Socket.io doesn't just send strings, it sends pretty much any javascript value, functions included. You can send a callback along with your data.

client:

saveSnail: function(snail) {
    // Core stats
    var data = {};
    data.ownerID = ig.game.sessionUserID;
    data.inDb = true;
    data.name = snail.name;
    // etc..

    console.log('saving snail');
    this.socket.emit("savesnail", data, function (err, snailid) {
      if (err) {
        return console.error(err);
      }
      snail.snailID = snailid;
      console.log('snail ID set: ' + snailid);
    });
}

server:

client.on('savesnail', function (data, cb) {
    console.log('save snail: ' + data.name);
    var snail = new Snail(data);
    snail.save(function (err, snail) {
        if (err) {return cb(err);} // Let the client handle the err
        var snailID = snail._id;
        console.log('saved snail ID ' + snailID);
        var conditions = {_id: data.ownerID},
            update = {$set: {newUser: false}}

        User.update(conditions,update,function(err){});
        console.log('user updated');
        cb(null, snailID);
    });
});

Upvotes: 1

Related Questions