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?
What is Bluebird JS? Bluebird JS is a fully-featured Promise library for JavaScript. The strongest feature of Bluebird is that it allows you to “promisify” other Node modules in order to use them asynchronously. Promisify is a concept applied to callback functions.
promisify. Returns a function that will wrap the given nodeFunction . Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function.
Promisifies the entire object by going through the object's properties and creating an async equivalent of each function on the object and its prototype chain. The promisified method name will be the original method name suffixed with suffix (default is "Async" ).
map. Given a finite Iterable (arrays are Iterable ), or a promise of an Iterable , which produces promises (or a mix of promises and values), iterate over all the values in the Iterable into an array and map the array to another using the given mapper function.
Why
thisends up beingundefinedin 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);
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().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With