Angular 中用于重新渲染视图模板的 Observable 等待和 setTimeout 的差异

Difference Observable wait and setTimeout for rerendering view template in Angular

我有用于排序数据的本地存储,这可能需要一段时间:

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();
        }
    );
}

元素数量为 5000 - 10000,由于 toTestCase,它需要 10 - 30 秒,这不是一个便宜的操作。我想为 loader 提供一个更加用户友好的界面:

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

<app-loading-overlay *ngIf="isLoader"></app-loading-overlay>在模板中。

但是当 isLoader = true 并且我可以在调试模式下看到它加载覆盖而不是渲染。

但是当我像这样用 setTimeout() 测试它的逻辑时:setTimeout(() => { this.isLoader = false; }, 100000) 一切正常并且加载程序可见。

我的可观察使用有什么问题以及如何在没有像 setTimeout() 或类似拐杖这样的冗余包装器的情况下修复它?

我认为这里的问题是 isLoader 没有更新他在 DOM 中的值。

让我们尝试使用 get/set,我们知道它们会更新它们的值。

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(() => {...});
}

然后在 html:

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

有了这个,我想应该知道了。尝试一下,如果它不起作用,我们将尝试另一种方法。

我想你需要调用 ngZone.run 到你的 ngZone.runOutsideAngular 的回调函数中,请看截图,你可以从这里查看 https://angular.io/api/core/NgZone#runOutsideAngular