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
this
ends up beingundefined
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);
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