Leahcim
Leahcim

Reputation: 41919

relationship between callbacks in node.js

This question arises from a homework question in the 10gen MongoDB class which uses Node.js, however, I'm not asking you to solve the homework (which is about Mongo) rather to explain relationship between two functions. In a session.js file, the method addUser is called on a users data object module like this

      users.addUser(username, password, email, function(err, user) {
                "use strict";

                if (err) {
                    // this was a duplicate
                    if (err.code == '11000') {
                        errors['username_error'] = "Username already in use. Please choose another";
                        return res.render("signup", errors);
                    }
                    // this was a different error
                    else {
                        return next(err);
                    }
                }

                sessions.startSession(user['_id'], function(err, session_id) {
                    "use strict";

                    if (err) return next(err);

                    res.cookie('session', session_id);
                    return res.redirect('/welcome');
                });
            });

In the users data object module, there's a function this.addUser like this

 this.addUser = function(username, password, email, callback) {
        "use strict";

        // Generate password hash
        var salt = bcrypt.genSaltSync();
        var password_hash = bcrypt.hashSync(password, salt);

        // Create user document
        var user = {'_id': username, 'password': password_hash};

        // Add email if set
        if (email != "") {
            user['email'] = email;
        }

        //node convention first arg to call back error, 2nd the actual data we're returning, callbackwith value if added user
        // look in session.js file that uses the UsersDAO to get a sense of how this is being used and
        // what type of callback is passed in.Task is to fill in code to add a user when one tries to signup

        // TODO: hw2.3

        callback(Error("addUser Not Yet Implemented!"), null);

    }

We're supposed to implement the callback that enables the addition of the User into the mongo database. I'm not asking you to tell me that. Rather, the fourth argument to the users.addUser function is a callback function function(err, user) { }. Also, the this.addUser function has callback as the fourth parameter, so the callback function from users.addUser runs inside this.addUser? Can you help clarify the relationship between these two? I know that a callback runs when a function has finished but I don't know why it's being passed into this.addUser

Upvotes: 0

Views: 746

Answers (1)

verybadalloc
verybadalloc

Reputation: 5798

so the callback function from users.addUser runs inside this.addUser?

That's exactly what is happening. As you probably already know, Javascript treats functions as first-class citizens. This means you can pass them around and return them just like other types. Functions are special because they have two additional fields in their prototype: the context in which they run and the function's code.

In your case, here is how this works:
1 - On the line users.addUser(username, password, email, function(err, user) {...}, you are calling this.addUser with the fourth parameter being an anonymous function.
2- this.addUser assigns a variable name to this anonymous function, calling it callback.
3- In the case of an error, callback is executed (since it is a function) with an error object Error("addUser Not Yet Implemented!") and null as parameters. These stand for err and user as declared in your first line.


An example that you are probably familiar with is that of setTimeout. This function is defined as: var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);. The method setTimeout does not really care what func is, as long it can execute it. Assume the following code, for example:

var delay = 30 * 1000;
document.getElementById("foo").innerHTML = "This text will change in "+delay/1000+" sec";
setTimeout(function(){
  document.getElementById("foo").innerHTML = "told ya!";
}, delay);

Here, again, we are passing a callback, that will be executed in the future. One cool thing is that this callback has access to the scope of setTimeout, which means it can use the variables defined in that scope. In the case of setTimeout, this isn't really useful, but, in your this.addUser, you have access to the error object that originated from the creation operation.

For more details on how callbacks work, check out these two answers.

Upvotes: 1

Related Questions