我正在研究angular和RxJs。我有一个组件来显示基于日期和 depo 选择的路线,以及该子组件中的一个表单来添加路线。 我创建了一个计划器服务,该服务注入到两个组件中。列表组件订阅 getLatestRoutesForDateDepo$ 和表单组件保存新路由。当我第一次选择新的日期 depo 并添加路线时,它效果很好。现在的问题是,当我更改日期和 depo 扫描过滤器时,也会聚合以前的数据并从列表中获取数组。 下面是代码。
export class RoutePlannerService {
constructor(routeClient:RouteClient) { }
private dateDepoSubject = new Subject<{date:Date,depo:DepoResource}>();
initialize(date:Date,depo:DepoResource){
this.dateDepoSubject.next({date,depo});
}
private getRoutesForDateDepo$ = this.dateDepoSubject.pipe(
switchMap(schedule => this.routeClient.getRoutesByDateAndDepo(schedule.date,schedule.depo.id))
);
private addRouteSubject = new Subject<CreateRoute>();
saveRoute(route:CreateRoute){
this.addRouteSubject.next(route);
}
getLatestRoutesForDateDepo$ = merge(this.getRoutesForDateDepo$,
this.addRouteSubject.asObservable().pipe(
// Save the operation to the backend
concatMap(action => this.sendHttpRequest(action))
))
.pipe(
scan((routes: RouteResource[], route: RouteResource) => {
debugger;
return [...routes, route];
})
);
private sendHttpRequest(route: CreateRoute): Observable<RouteResource> {
return this.routeClient.post(route)
.pipe(
catchError(err => {
return EMPTY;
})
));
}
}
路线列表
routes$ = this.routePlannerService.getLatestRoutesForDateDepo$;
search() {
this.routePlannerService.initialize(new Date(this.date), this.depo)
}
路线表格
save(route: RouteResource): void {
this.routePlannerService.saveRoute(data);
}
你的问题在于getLatestRoutesForDateDepo$
的定义:
getLatestRoutesForDateDepo$ = merge(
this.getRoutesForDateDepo$,
this.addRouteSubject
).pipe(
scan((routes, route) => [...routes, route], [])
);
有了这个定义,两个来源的所有排放都使用scan
累积到一个阵列中。
由于您希望在getRoutesForDateDepo$
发出时重置,因此您可以将merge
嵌套在如下所示的switchMap
中:
getLatestRoutesForDateDepo$ = this.getRoutesForDateDepo$.pipe(
switchMap(routes => merge(
of(routes),
this.addRouteSubject
).pipe(
scan((routes, route) => [...routes, route], [])
)
);
在这里,我们不是包括getRoutesForDateDepo$
作为merge
源,而是使用它来触发switchMap
,它返回一个可观察量,该可观察量将getRoutesForDateDepo
排放与addRouteSubject
的所有未来排放合并在一起。每当getRoutesForDateDepo$
发出时,我们的switchMap
都会创建一个新的内部可观察量,从而有效地重置您的scan
。
希望这是有道理的,但这里有一个有效的StackBlitz。
谢谢你的堆栈闪电战。这很有帮助。
在应用中尝试如下操作:
scan((routes: RouteResource[], route: RouteResource) => {
if (Array.isArray(route)) {
return route;
}
return [...routes, route];
})
如果扫描的第二个参数是数组,则返回数组。否则,它将发出的路由添加到数组中。
更新的堆栈闪电战在这里: https://stackblitz.com/edit/angular-ivy-eckbag
让我知道这是否适合您。