1

Simple example of my problem

Consider the following situation, where I have a few functions (a and b) that I used in a promise-chain in c:

class SomeClass {
    constructor(){
        this.v1 = 1;
        this.v2 = 2;
    }

    a() {
        return new Promise((resolve, reject) => {
            console.log('a', this.v1);  // Do something with `this`
            resolve();
        });
    }

    b() {
        return new Promise((resolve, reject) => {
            console.log('b', this.v2);   // Do something with `this`
            resolve();
        });
    }

    c() {
        return this.a().then(this.b);   // passing b as argument
    }
}

When I call c and run the chain of promises, this is undefined in b.

const sc = new SomeClass();

sc.c().then(() =>{
    console.log('done')
}).catch((error) => {
    console.log('error', error);
});

Output:

a 1
error [TypeError: Cannot read property 'v2' of undefined]

I know that arrow functions inherit the outer this, but I am not sure why it is undefined since I am invoking it from c.

Tyler
  • 17,669
  • 10
  • 51
  • 89

1 Answers1

2

The problem is here:

this.a().then(this.b)

because the resulting function retrieved by this.b becomes unbound from this (you don't actually invoke it in the way stated in your question).

You can solve it in a way that is consistent with the rest of your code, by using an arrow method to preserve scope:

this.a().then(obj => this.b(obj))

or you can use .bind to achieve a similar result:

this.a().then(this.b.bind(this))
spender
  • 117,338
  • 33
  • 229
  • 351
  • Which option is a more popular pattern when you have a long chain of class functions? – Tyler Nov 05 '15 at 11:47
  • 1
    I'd say it's "6 of one, half a dozen of the other" choice. I'm rather fond of using arrow functions as a scope preserving mechanism and it's certainly consistent with the rest of your code. – spender Nov 05 '15 at 11:50