ebbflowgo ebbflowgo - 4 months ago 30
Javascript Question

ES6 Class Promise Chain -- Accessing 'this'

I'd like to reference a class property in my second promise. However, in the class function pTwo, 'this' is undefined. I understand that I'm in the promise scope, how might I access the PromiseChain instance scope?

Using ES6 and native promises.



class PromiseChain {
constructor(){
this.food = 'Pasta';
this.type = 'Italian';
}

pOne() {
console.log('pOne');
return Promise.resolve();
}

pTwo() {
console.log('pTwo');
try {
console.log(this.food);
} catch (e) {
// can't read 'food' of undefined!
console.log(e);
}
return Promise.reject()
}

work() {
console.log('Get to work!');
this.pOne().then(this.pTwo).catch((error) => {
console.log(error);
})
}
}

new PromiseChain().work();




Answer

This is simple, you need to bind your call of pTwo to the correct scope, in Javascript we can do this with the bind() method.

Therefore:

this.pOne().then(this.pTwo.bind(this)).catch((error) => {

Will bind your call to pTwo to the correct scope, resulting in:

Get to work!
pOne
pTwo
Pasta
undefined

To be printed; if you want the last undefined to return something, pass a message in your reject parameter.

If you do not want to clutter your code base with lots of .bind(this) you could explicitly set a reference to this in the current scope and pass it as a parameter to each of your promises; in your case in the work method declare:

work() {
    var that = this;
    console.log('Get to work!');
    this.pOne().then(this.pTwo(that).catch((error) => {
        console.log(error);
    }));
}

Note that now pTwo accepts an argument of that, now inside of pTwo we can do the following:

pTwo(parentScope) {
    console.log('pTwo');
    try {
        console.log(parentScope.food);
    } catch (e) {
        // can't read 'food' of undefined! 
        console.log(e);
    }
    return Promise.reject()
}

Notice that we pass the parameter parentScope which allows us to ref the correct scope.