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
我有用于排序数据的本地存储,这可能需要一段时间:
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