Why my code works with arrow function and broken with bind?

109 views Asked by At

I have thought that bind(this) is an equivalent of the arrow function however I have met an issue(

This is a store which purpose to track delayed requests. I am using the orbitjs library to save everything into IndexedDB. It provides api which allows to subscribe to db changes, so here my store:

export class DelayedRequestsStore implements IDelayedRequests {
    add = addHttpRequest;
    list = queryHttpRequests;
    remove = removeHttpRequest;

    @observable private _delayedRequestsCount = 0;

    @computed get any(): boolean {
        return this._delayedRequestsCount > 0;
    }

    @computed get empty(): boolean {
        return !this.any;
    }

    constructor(db: Sources) {
        db.source.on('update', () => {
            this._updateDelayedRequestsCount();
        });
        this._updateDelayedRequestsCount();
    }

    private async _updateDelayedRequestsCount(): Promise<void> {
        const delayedRequests = await this.list();
        runInAction(() => {
            this._delayedRequestsCount = delayedRequests.length;
        });
    }
}

See that code on constructor

    constructor(db: Sources) {
        db.source.on('update', () => {
            this._updateDelayedRequestsCount();
        });
        this._updateDelayedRequestsCount();
    }

And some code on react:

<button onClick={async () => {
    await notifyServer(); 
    await clearRequestsFromIndexedDb();
    goToAnotherPage();
})>Cancel</button>

Everything works well until I have not changed the constructor code to

    constructor(db: Sources) {
        db.source.on('update', this._updateDelayedRequestsCount.bind(this));
        this._updateDelayedRequestsCount();
    }

With that change I have not seeing any errors in console but Cancel button is not working. I have debugged and found that notifyServer has been called, then clearRequestsFromIndexedDb has been called but goToAnotherPage not called, like if error occured in clearRequestsFromIndexedDb, but no errors. SO I rollbacked back to arrow function everything works again. Does it can affect anything? Or the problem actually in some other place I am missing?

1

There are 1 answers

2
Jirka Svoboda On

I see that you bound this only to db.source.on('update', ... ). But the call for this._updateDelayedRequestsCount() in your constructor has no binding. This could be a problem.

You can explicitly bind this to every call of you method like this:

constructor(db: Sources) {
    this._updateDelayedRequestsCount = this._updateDelayedRequestsCount.bind(this);
    
    db.source.on('update', this._updateDelayedRequestsCount);
        
    this._updateDelayedRequestsCount();
    }

Maybe it will fix your problem.