我正在创建一个Angular应用程序,该应用程序通过websocket连接发送和接收数据。我有一个服务SocketService
,该服务打开并保持连接,该服务已注入到其他服务中。
网络套接字上的每条消息看起来像{ctrl: string, payload: any}
,并且为Subject
中的每个控制器(ctrl
)创建了一个SocketService
,其他服务可以订阅,因此每个服务仅订阅预定的消息。
随着服务和控制器数量的增加,我在Subjects
中拥有越来越多的SocketService
,现在我想知道让每个服务直接订阅websocket消息是否更有效并让服务本身检查消息是否是针对此消息的。但这意味着套接字上的每条消息都会触发大量订户。
// in the socketservice
private createSocketSubscription(): void {
// Snipped from the socket service when receiving messages on the socket connection
this._subscription = this._subject.pipe(map(msg => JSON.parse(msg.data))).subscribe((data) => {
const ctrl = data[this.CTRL] || 'common';
this._registry[ctrl].next(data[this.PAYLOAD]);
}
}
public registerController(ctrl: string, def?: any) {
if (!(this._registry[ctrl]))
this._registry[ctrl] = new BehaviorSubject(def?def:{});
return this._registry[ctrl].asObservable();
}
// in some service
constructor(private socketService: SocketService) {
this.socketService.registerController('something').subscribe(payload=> {
// do stuff with the payload
});
}
与
// in some service
constructor(private socketService: SocketService) {
this.socketService.getSubject().subscribe(data => {
if(data['ctrl'] === 'something') {
// do stuff with the payload
}
});
}
哪种方法更有效?甚至有什么不同?我省去了停止和取消订阅的过程,我只是想知道对多个主题进行少量订阅还是对单个主题进行多个订阅比较好?
答案 0 :(得分:1)
如果订阅应该是最终目的地,则其他任何内容都应该是管道。在角度应用程序中,最好的方法是完全避免订阅,并在需要流中数据时在模板中使用async
管道。
在您的示例中
.subscribe(() => {
.next
}
表示一个流应该触发另一个流,正确的方法是在mergeMap
加入switchMap
流并处理时使用.next
,.subscribe
等它发出。
您可以使用ctrl
运算符代替filter
映射
this.socketService.getSubject().pipe(
filter(data => data['ctrl'] === 'something'),
).subscribe(data => {
// do stuff with the payload
});
我推荐的方式
// in some service
public data$: Observable<any>;
constructor(private socketService: SocketService) {
this.data$ = this.socketService.getSubject().pipe(
filter(data => data['ctrl'] === 'something'),
// map(data => data), // do something
);
}
和模板中
<ng-container *ngIf="data$ | async as data">
{{ data | json }}
</ng-container>