简体   繁体   中英

node.js / javascript — nested callbacks

function MyClass() {
    this.a = "me a";
    this.b = "me b";
};

MyClass.prototype.changeB = function(callback) {
    this.a = "now me A";
    doAnotherFunction(function(err, data) {
        this.b = "now me B";
    callback(null, this.b);});
};

function doAnotherFunction(callback) {
    callback(null, null);
};

main();

function main() {
    var myclass = new MyClass();
    myclass.changeB(function(err, data) {
    console.log("B: " + myclass.b + ", data: " + data);});
    console.log(JSON.stringify(myclass));
}


When this runs:
B: me b, data: now me B
{"a":"now me A","b":"me b"}

Go easy on me, I'm new to javascript and to posting here.

My question is why does 'this.b' not get changed in the original MyClass instantiation? I've read in here where javascript does not have block scope (only function scope). If that was the reason, then why wouldn't it treat 'this.b' as 'undefined' where it sets it to "now me B"?

Thanks!

The anonymous callback function you pass to the method creates a new scope, so when you say this.b inside the callback, it's not the same b anymore, but a new one.

One common way to solve it is to create a reference to the this you want to access, outside the callback:

var self = this;

Then you can reference self.b inside the callback.

Here is a good read to begin with.

For your specific example, you could code it like this, saving a reference to the this of the MyClass instance:

MyClass.prototype.changeB = function(callback) {
    var me = this;
    this.a = "now me A";
    doAnotherFunction(function(err, data) {
        me.b = "now me B";
        callback(null, me.b);
    });
};

Example using bind in response to the suggestion:

MyClass.prototype.changeB = function(callback) {
    this.a = "now me A";
    var fn = function(err, data) {
        this.b = "now me B";
        callback(null, this.b);
    });
    // the first parameter to bind will be the 'this'
    // visible from inside the function
    doAnotherFunction(fn.bind(this));
};

EDIT : To find out what this was in your example, try adding some logging:

MyClass.prototype.changeB = function(callback) {
    var me = this;
    this.a = "now me A";
    doAnotherFunction(function(err, data) {
        // Use this['b'] notation to avoid errors using this.b,
        // if this.b doesn't already exist.
        console.log(me, typeof me, this, typeof this, this['b']);
        this.b = "now me B";
        callback(null, this.b);
    });
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM