Object method with ES6 / Bluebird promises

2019-01-01 14:08发布

问题:

I am using node v0.11.14-nightly-20140819-pre on Windows with harmony flag.

I have JavaScript object with two methods defined in its prototype:

function User (args) {
    this.service= new Service(args);
}

User.prototype.method2 = function (response) {
    console.log(this); // <= UNDEFINED!!!!
};

User.prototype.method1 = function () {
    .............
    this.service.serviceMethod(args)
        .then(this.method2)
        .catch(onRejected);
};

function onRejected(val) {
    console.log(val);
}

serviceMethod of Service object returns a promise.

When I use User object like below:

let user = new User(args);
user.method1();

this in method2 of object User ends up undefined when called by then once promise is fulfilled.

I tried using both ES6 and Bluebird promise implementation.

Why this ends up being undefined in this case?

回答1:

Why this ends up being undefined in this case?

Because you\'re passing a function, not a method-bound-to-an-instance. This problem is not even promise-specific, see How to access the correct `this` context inside a callback? for the generic solution:

….then(this.method2.bind(this))… // ES5 .bind() Function method

….then((r) => this.method2(r))… // ES6 arrow function

However, Bluebird does offer an other way to call the function as a method:

this.service.serviceMethod(args)
    .bind(this)
    .then(this.method2)
    .catch(onRejected);


回答2:

I should add that this is a generic Javascript issue and can also be solved using plain javascript features. For example, you could also do this:

User.prototype.method1 = function () {
    .............
    this.service.serviceMethod(args)
        .then(this.method2.bind(this))
        .catch(onRejected);
};

This uses Function.prototype.bind() which is built into Javascript and present on every function. This creates a function stub (which is what is passed to .then() and that stub will automatically reattach the desired this value before calling method2().