【问题标题】:RxJS many Subjects with few Subscriptions vs Single Subject with many SubscriptionsRxJS 多主题订阅少 vs 单主题多订阅
【发布时间】:2020-09-20 19:08:13
【问题描述】:

我正在创建一个 Angular 应用程序,它通过 websocket 连接发送和接收数据。我有一项服务SocketService 打开并保持连接,该服务被注入到其他服务中。

websocket 上的每条消息都类似于{ctrl: string, payload: any},并且为SocketService 中的每个控制器(ctrl)创建了一个Subject,其他服务可以订阅这些消息,因此每个服务只订阅预期的消息为了它。

随着服务数量的增加以及控制器数量的增加,我在SocketService 中有越来越多的Subjects,现在我想知道让每个服务直接订阅 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
    }
  });
}

哪种方法更有效,甚至会有所作为?我省略了停止和取消订阅的过程,我只是想知道是对多个主题进行少量订阅还是对单个主题进行多次订阅更好?

【问题讨论】:

  • 许多崇拜者,只有一位真神。

标签: angular rxjs


【解决方案1】:

订阅如果应该是最终目的地,其他任何东西都应该是管道。在 Angular 应用中,最好的方法是完全避免订阅,并在需要来自流的数据时在模板中使用 async 管道。

在你的例子中

.subscribe(() => {
    .next
  }

意味着一个流应该触发另一个流,正确的做法是使用mergeMapswitchMap等,当.next加入.subscribe流并处理它的发射。

您可以使用filter 运算符代替ctrl 地图

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 2021-10-14
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    相关资源
    最近更新 更多