【发布时间】:2021-02-09 00:51:46
【问题描述】:
我想合并三个流,它们分别代表数组的初始状态、添加的元素和编辑的元素。预计一次只执行添加或编辑排放。
但是,combineLatest 会触发两次,这会导致向数组添加两次新行程。
private initialTripsSubject = new BehaviorSubject<Trip[]>([]);
initialTrips$ = this.initialTripsSubject.asObservable();
private newTripSubject = new BehaviorSubject<Trip>(null);
addedTrip$ = this.newTripSubject.asObservable();
private updatedTripSubject = new BehaviorSubject<Trip>(null);
editedTrip$ = this.updatedTripSubject.asObservable();
updatedTrips$ = combineLatest([
this.initialTrips$,
this.addedTrip$,
this.editedTrip$
]).pipe(
map(([existingTrips, newTrip, editedTrip]) => {
if (editedTrip) {
existingTrips.map(item => {
if (editedTrip && item.id === editedTrip.id) {
item.country = editedTrip.country;
item.departureDate = editedTrip.departureDate;
item.arrivalDate = editedTrip.arrivalDate;
item.notes = editedTrip.notes;
}
return item;
});
}
if (newTrip) {
existingTrips.push(newTrip);
}
return existingTrips;
}
)
);
事件从这个函数被发送到 addedTrip$
addTrip(newTrip: Trip): void {
this.newTripSubject.next(newTrip);
}
在模板中,流通过| async使用
<table *ngIf="(trips$ | async) as trips; else emptyTrips" class="table table-striped">
我的假设是当addedTrip$ 被处理时,它会改变initialTrips$ 的状态,从而导致combineLatest 的第二次触发。
尝试将流的合并拆分为两部分:merge(editedTips, addedTrip) 和 combineLatest([initialTrips, resultOfMerge]),但没有帮助。
如何避免合并流的双重触发?
更新
Trip$ 在组件中初始化
trips$ = this.tripService.updatedTrips$$.pipe(
catchError(err => {
this.errorMessageSubject.next(err.message);
return EMPTY;
}
)
);
更新 2
链接到 StarBlitz 的问题
https://stackblitz.com/edit/angular-combinelatest-repeat-pf7q2g?file=src/app/app.component.html
【问题讨论】:
-
trips$是如何定义的? -
combineLatest将在所有 3 个源 observables 发射后第一次发射,然后它会在任何 observables 发射时发射一次。在您的情况下,它将发出初始状态,然后在您调用addTrip()后发出。你是什么意思“避免双重射击”?你想省略哪个发射? -
@BizzyBob 更新了 trip$ 初始化。 “零”发射对我来说很好,因为所有值都是空/空的。当我通过
addTrip函数使用Subject提交事件时,我观察到updatedTrips$的两次发射(但addTrip方法仅被调用一次) -
有趣。每次调用 addTrip 时,我只期望一个发射。你能在 StackBlitz 中重现吗?
-
@ryzhman 我建立了一个非常相似的简化应用程序stackblitz.com/edit/angular-combinelatest-repeat。如您所见,每次添加行程时,
combineLatest仅被调用一次。请分享一个完整的可重现示例。