我在使用可观察对象和管道方面很挣扎,我想将一个可观察对象中的一项添加到包含相同类型项列表的另一个可观察对象中。
我有类型X。在类型X中,我有一个可观察的数组:
readonly arrayOfx$: Observable<X[]>;
我也只有X类型的观测值:
private readonly _x$: Observable<UpdateOfX>;
interface UpdateOfX {
x: X,
updateState: "Add" | "Modified" | "Removed"
}
所有这些代码都在服务类中,其中服务仅应公开X数组。我想使用异步管道在html中显示数组中的数据,并且此功能部分可以正常工作。主机和客户端通过signalR技术进行连接,并在onConnected上检索到X类型的项目数组。但是,随着应用程序的运行,可以在后端创建X类型的新项目,可以更改或删除现有项目,并且在发生这种情况时,仅会通过signalR连接和修改状态发送该项目。
在前端,必须将此项目添加到已检索的类型为X的项目数组中。在服务中,使用了管道技术,我的问题是,如何添加以后获得的单个项目到我之前检索的项目列表的时刻了?
constructor() {
this.arrayOfx$ = this._someSignalRHelperService.retrieveMultipleItems$.pipe(
tap((xArray: X[]) => console.log(xArray)),
//can I somehow get the a later created x from the server here...
);
this._x$ = this._someSignalRHelperService.retrieveOneItem$.pipe(
tap((updateOfX: UpdateOfX) => console.log(updateOfX)),
map((updateOfX: UpdateOfX) => {
//process the updateState
//... or must I do something here to get x into x[]?
})
);
}
由于使用了SignalR,因此当创建了一个X类型的新项时,当客户端收到X类型的新项时,后端将处于控制状态。
答案 0 :(得分:0)
您可以使用combineLatest()
,并在收到两次发射后立即进行所需的任何处理:
constructor() {
this.combinedOfX$ = combineLatest(
this._someSignalRHelperService.retrieveMultipleItems$,
this._someSignalRHelperService.retrieveOneItem$
).pipe(
map(([singleOfX, multipleOfX]) => {
// do your adding or mapping and whatever here.
})
)
}
不确定那是否是设计使然,但是让前端(客户端)处理数据的问题并不是那么理想。现在,您的唯一事实来源是基于您的客户端的,这台不同的计算机具有不同的处理速度,并可能导致细微差别和显示不一致。另外,从某种意义上说,代码将很混乱,因为您现在每次更新arrayOfX
时都需要检查整个singleOfX
-您需要检查它是否存在于当前列表中(如果是) ,编辑/删除;否则,追加到列表中。如果用户意外刷新浏览器怎么办?您丢失了所有处理程序。
由于您已经在使用SignalR,因此最好让服务器处理所有数据,并让服务器成为事实的唯一来源。然后,您只需要订阅一个集线器并收听arrayOfX
的更改;而且几乎不关心单个更新。