[英]Cache state in Map of RxJS Subjects by id in Angular service
我为每个ownerId
收集了一组小部件。 我正在尝试使用Map<string, ReplaySubject<Widget[]>>
在 Angular 服务中缓存这些 collections 的 state 。
@Injectable({
providedIn: 'root',
})
export class WidgetService {
private readonly widgetsByOwnerId: Map<string, ReplaySubject<Widget[]>> =
new Map<string, ReplaySubject<Widget[]>>();
constructor(
private readonly httpClient: HttpClient
) {}
getWidgets(ownerId: string): Observable<Widget[]> {
if (!this.widgetsByOwnerId.has(ownerId)) {
const widgets$ = this.httpClient.get<Widget[]>(`api/${ownerId}/widgets`);
const widgetsCache$ = new ReplaySubject<Widget[]>(1);
widgets$.subscribe(widgetsCache$);
this.widgetsById.set(ownerId, widgetsCache$);
}
return this.widgetsById.get(ownerId).asObservable();
}
createWidget(widget: Widget): Observable<Widget> {
return this.httpClient
.post<Widget>(`api/${widget.ownerId}/widgets`, widget)
.pipe(
tap((createdWidget): void => {
this.widgetsByOwnerId.forEach((widgets$, ownerId) =>
widgets$.pipe(take(1)).subscribe({
next: (widgets: Widget[]) => {
if(createdWidget.ownerId == ownerId || isOwnedById) {
widgets.push(createdWidget);
widgets$.next(widgets);
}
},
})
);
}
);
}
//additional CRUD functions excluded for brevity
}
一些特殊类型的小部件可以由多个小部件所有者拥有,因此 WidgetService 中的一些 CRUD 函数可以在多个ownerId
的WidgetService
上ReplaySubject
next()
。 在上面的示例中,为了简洁起见,我使用isOwnedById
省略了其中的一些逻辑。
该服务的消费者如下所示:
@Component({
selector: 'app-widgets',
templateUrl: './widgets.component.html',
})
export class WidgetsComponent implements OnInit, OnDestroy {
widgets: Widget[];
private readonly ngUnsubscribe$: Subject<unknown> = new Subject();
constructor(
private readonly widgetService: WidgetService
) {}
ngOnInit(): void {
const ownerId = this.getOwnerId();
this.getWidgets(ownerId);
}
ngOnDestroy(): void {
this.ngUnsubscribe$.next();
this.ngUnsubscribe$.complete();
}
private getOwnerId(): string {
...
}
private getWidgets(ownerId: string): void {
this.widgetService
.getWidgets(ownerId)
.pipe(takeUntil(this.ngUnsubscribe$))
.subscribe({
// TODO: this next is called once when first subscribed, but not when future widgets are created
next: (widgets) => {
this.widgets = widgets;
},
});
}
}
由于某种原因,当消费组件第一次初始化时,它成功地获取了缓存的Widget[]
。 但是,当像WidgetService.createWidget()
这样的 CRUD 操作在其他组件中执行时(而WidgetComponent
的实例仍然存在,例如在WidgetComponent.ngOnDestroy()
之前),这个WidgetComponent
消费者永远不会收到next()
更新(如在TODO
评论)。
关于如何解决这个问题的任何建议,以便消费者继续从WidgetService
的ReplaySubject
获得更新? 谢谢。
这个问题与这个问题有点相似,但差异很大,以至于我无法弄清楚如何使他们的答案适应这个用例。
我认为这里的主要问题是:
const widgets$ = this.httpClient.get<Widget[]>(`api/${ownerId}/widgets`);
const widgetsCache$ = new ReplaySubject<Widget[]>(1);
widgets$.subscribe(widgetsCache$);
httpClient
创建一个 finity Observable 意味着一旦请求完成或失败,它将完成。
因此,您的ReplaySubject
作为Observer
传递给subscribe
方法将完成,您将不会再收到任何事件。
要修复它,您可以将subscribe
实现替换为以下内容:
widgets$.subscribe(res => widgetsCache$.next(res));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.