0

I have an problem and I guess the solution is using callbacks. But I'm not sure how. When starting node.js the following code gets called:

// create a new player and insert in the database
// the player gets inserted in the database correctly
var player1 = new player();

console.log(player1.id); // undefined

My constructor looks like this:

function Player(id) {

    // if we don't have a id, this player needs to be created
    this.id = (typeof id !== 'number') ? this.createPlayer() : this.setId(id);

}

Then I create a player in the database:

Player.prototype.createPlayer = function () {

    var playerId = 0;

    connection.query("INSERT INTO players SET `created_at` = now()", function (err, result) {

        if (result) {

            playerId = result.insertId;

            console.log("Successfully inserted player no. " + playerId);

            this.id = parseInt(playerId, 10);

            return this.id;

        } else {

            console.log("Something went wrong: " + err);

        }

    });

};

My guess is I need some form of callback, but I'm not sure how I will do this. A small push in the right direction would be great!

Martijn
  • 373
  • 1
  • 4
  • 15
  • possible duplicate of [how to return value from callback function](http://stackoverflow.com/questions/6847697/how-to-return-value-from-callback-function); in brief, ``return this.id`` does not do what you think it does. – Louis Jan 23 '14 at 13:03

3 Answers3

0

This is the use case of node.js EventEmitter. You can use events to let the application know that your object initialization is completed and it is ready to be used. (I haven't tried the code, but its should work this way, let me know if it doesn't)

var EventEmitter = require('events').EventEmitter;
var util = require('util');

// Define your class like
function Player(id) {   

    // if we don't have a id, this player needs to be created
    this.id = (typeof id !== 'number') ? this.createPlayer() : this.setId(id);
}
util.inherits(Player, EventEmitter);

Player.prototype.createPlayer = function (cb) {
    connection.query(sql, function (err, result) {
        if (result) {

            // to avoid triggering event before binding.
            process.nextTick(function () {
                // success! passing null as first argument and data as second
                this.emit('load', null, this.id);
            });

        } else {

            process.nextTick(function () { 
                this.emit('load', err, null); // passing err as first argument
            });

        }
    });
};

// And, use your class like
var player1 = new player();

player1.on('load', function (err, id) {
    console.log(player1.id);
});

As per you comment, createPlayer is not always called, i.e. only on certain condition. so you could use the same emit in case where you don't want to call createPlayer.

Hope that helps

Salman
  • 9,299
  • 6
  • 40
  • 73
  • Thank you, that helped. I had to change some code because I forgot we changed scope. In the callback of the query this =/= player anymore. – Martijn Jan 23 '14 at 13:57
0

In Node.js there are a number of ways to queue up a callback function. They are all documented here: http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg

One example for adding two numbers and passing the result to a callback would be:

function addWithCallback(a, b, callback) {
    process.setImmediate(callback, a+b);
}

Just like that you could do:

addWithCallback(1,3,foo);

and foo would be queued into the event loop and passed the result of 1+3 at execution time. Also check out:

http://howtonode.org/understanding-process-next-tick and setImmediate vs. nextTick

Definitely a complete solution to your question, but hopefully the "small push in the right direction" you wanted :)

Community
  • 1
  • 1
Owen
  • 1,652
  • 2
  • 20
  • 24
-2

Basically a callback is just a function to call then something is done

ie

function asyncAdd(v1,v2,callback){
  var total = v1 + v2;
  callback(total);
}

asyncAdd(1,2,function(t){
  alert(t);
});

Contrast this with:

syncAdd(v1,v2){
  return total;
}

Hopefully this should give you enough to get started.

Much better explanation here: http://recurial.com/programming/understanding-callback-functions-in-javascript/

Chris Charles
  • 4,406
  • 17
  • 31
  • Maybe I misunderstood the question, but this answer doesn't seem right. The point to callbacks is generally to keep execution from being blocking, so ideally a callback should be queued in the event loop, not executed synchronously at the end of the function... e.g.: http://nodejs.org/api/timers.html#timers_setimmediate_callback_arg – Owen Jan 23 '14 at 13:56