Search code examples
angulartypescriptrxjs6angular2-observables

Difference Observable wait and setTimeout for rerendering view template in Angular


I have local storage for the sort data which can take a while:

private store: IBacktest[] = [];

public setStore(content: string): Observable<void> {
    return new Observable<void>((observer) => {
            this.store = content
                .trim()
                .split('\n')
                .map(item => toTestCase(item))
                .sort((a, b) => b.profitToDropDown - a.profitToDropDown);
            observer.next();
            observer.complete();
        }
    );
}

Amount of elements 5000 - 10000 and it get 10 - 30 seconds because of toTestCase, not a cheap operation. And I want to render loader a more user-friendly interface:

this.isLoader = true;
this.backtestService
    .setStore(content)
    .pipe(finalize(() => {
        this.isLoader = false;
    }))
    .subscribe(() => {...});

And <app-loading-overlay *ngIf="isLoader"></app-loading-overlay> in template.

But when isLoader = true and I can see it in debug mode loading-overlay not rendering.

But when I try to test its logic with setTimeout() like this: setTimeout(() => { this.isLoader = false; }, 100000) all work properly and loader is visible.

What is the problem with my observable use and how to fix it without redundant wrappers like setTimeout() or something similar crutches?


Solution

  • I think the problem here is that isLoader is not updating his value in the DOM.

    Let's try using get/set that we know they will update they value.

    private _isLoader: boolean = false;
    public get isLoader() {
       return this._isLoader;
    }
    public set isLoader(value: boolean) {
       this._isLoader = value;
    }
    callsetStore(): {
       this.isLoader = true;
       this.backtestService
        .setStore(content)
        .pipe(finalize(() => {
            this.isLoader = false;
        }))
        .subscribe(() => {...});
    }
    

    Then in the html:

    <app-loading-overlay *ngIf="isLoader"></app-loading-overlay>
    

    With that, I think it should work know. Try it and if it doesn't work we will try another approach.