[英]Angular Observables: How to optimize subscription / subscribe vs async
我有以下组件:
@Component({
selector: 'summary-dialog',
templateUrl: './summary-dialog.component.html',
styleUrls: ['./summary-dialog.component.css']
})
export class SummaryDialogComponent implements OnInit {
entriesSummaries: GuiEntrySummary[];
private interval;
constructor(private backendService: BackendService,
private dialogRef: MatDialogRef<SummaryDialogComponent>,
@Inject(MAT_DIALOG_DATA) private data: {
eventDbid: number,
timerState: TimerState,
entries: IGuiEntry[]
}) { }
ngOnInit(): void {
this.entriesSummaries = this.data.entries.map(entry => new GuiEntrySummary(entry));
this.getSummaries();
// automatic refresh the entries summaries every 10 secs
this.interval = setInterval(() => {
this.getSummaries();
}, 10000)
this.dialogRef.afterClosed().subscribe(() => clearInterval(this.interval));
}
private getSummaries(): void {
this.backendService.getSummaries(this.data.eventDbid, this.data.timerState.elapsedSeconds).subscribe(entriesSummaries =>
entriesSummaries.forEach(entrySummaries =>
this.entriesSummaries.find(entry => entry.dbid === entriesSummaries.dbid).summaries = entrySummaries.summaries
)
);
}
}
该组件是一个对话框。 每个条目( data -> entries )都是对话框中的一行。 已经解析的条目将被传递到对话框中,这是显示数据的基础。 每个条目都将使用摘要数组进行丰富。 该组件应每 10 秒刷新一次所有条目的摘要。
但我的主要问题是理解如何以可接受的方式实现这个用例。
在这种情况下订阅组件真的很糟糕吗? 我这样做主要是因为模板应该一直显示现有数据,即使是在从 backendService 获取新数据的短时间内。
如果我以异步方式执行此操作(例如:
<div *ngIf="( getAllEntriesSummaries |async ) as entriesSummaries">
),我会想象,容器不会在获取新数据的确切时刻显示。 此外,我还需要模板中的另一个 function 调用,它将当前数据的数据与新数据合并?!
使用我当前的解决方案(在组件中可能使用反订阅模式),我有一个非常干净的模板:
<h2 mat-dialog-title>Entries Summaries</h2>
<mat-dialog-content class="mat-typography">
<div class="grid">
<div *ngFor="let entry of entriesSummaries; let i = index" class="entry-row"
[ngClass]="i % 2 === 0 ? 'bg-even' : 'bg-odd'">
<!--entry row -->
</div>
</div>
</mat-dialog-content>
您可以像这样使用timer
RxJS 运算符:
entriesSummaries$: Observable<GuiEntrySummary[]>;
ngOnInit() {
this.entriesSummaries$ = timer(0, 10000).pipe(exhaustMap(() => this.getSummaries()));
}
private getSummaries(): Observable<GuiEntrySummary[]> {
return this.backendService.getSummaries(this.data.eventDbid, this.data.timerState.elapsedSeconds).pipe(tap(() => /* side effects */));
}
<div *ngIf="(getAllEntriesSummaries$ | async) as entriesSummaries">
从文档中:
timer
返回一个 Observable ,它发出无限的递增整数序列,具有恒定的时间间隔,您可以在这些发射之间选择周期。 第一次发射发生在指定的到期时间之后。 最初的延迟可能是一个日期。 默认情况下,此运算符使用 {@link asyncScheduler} {@link SchedulerLike} 来提供时间概念,但您可以将任何 {@link SchedulerLike} 传递给它。 如果没有指定 period,output Observable 只会发出一个值,0。否则,它会发出一个无限序列。
我不会说订阅组件是一种不好的做法,但是,建议使用async
pipe 以获得更好的性能,尤其是在使用 OnPush 更改检测时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.