RxJs 合并运算符以获取最新数据并使用扫描运算符进行累积



我正在研究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

让我知道这是否适合您。

最新更新