Angular 8-从两个不同的组件订阅一项服务

问题描述 投票:0回答:2

我有一个角度服务和两个使用此服务的不相关组件:

服务代码:

const url = 'ws://localhost:8080

@Injectable({
   provideIn: 'root',
})

export class MyService{

  public subject: Subject<Status>;

  constructor(wsService: WebSocketService){
    this.subject = <Subject<Status>>wsService.connect(url).map(
       (response: MessageEvent): Status => {
          let data = JSON.parse(response.data);
          return data;
        }
    );
  }

  getObs(){
    return this.subject.asObservable();
  }

  sendMsg(msg){
    this.subject.next(msg);
  }

}

组件1:

@Component

.. some irrelevant code ..

constructor(private service: MyService){
  this.service.getObs().subscribe( data => 
    console.log('comp1');
  );

  console.log('comp1 - after subscribe');
}

.. some irrelevant code ..

组件2:

@Component

.. some irrelevant code ..

constructor(private service: MyService){
  this.service.getObs().subscribe( data => 
    console.log('comp2');
  );

  console.log('comp2 - after subscribe');
}

.. some irrelevant code ..

我在控制台中得到以下输出:

comp1

comp1-订阅后

comp2-订阅后

我认为我应该得到的输出:

comp1

comp1-订阅后

comp2

comp2-订阅后

谁能解释这个问题是什么?

注意:我将我的服务添加到了模块提供程序中,并得到了相同的结果。

谢谢。

这是webSocketService的代码:https://github.com/elliotforbes/ng-chat/blob/master/src/app/common/services/websocket.service.ts

angular service components observable subject
2个回答
1
投票

您应该控制自己的主题,而不是piggy依WebSocketService.connect并假设您将获得期望的行为。

从链接到您发布的WebSocketService的源代码,我们看到它是一个简单的主题。您想要的功能-在订阅时发出一个值(假设存在)-由ReplaySubject提供。

您应该声明一个本地ReplaySubject,这是您的组件将预订的。然后,您将订阅您的WebSocketService。来自WebSocketService的任何响应都将映射到一个状态,然后发送到您的本地主题。

const url = 'ws://localhost:8080

@Injectable({
   provideIn: 'root',
})

export class MyService{

  // Declare local ReplaySubject that emits the last value upon subscription
  private subject: Subject<Status> = new ReplaySubject<Status>(1);

  constructor(wsService: WebSocketService) {
    // Subscribe to the web socket service.
    // Subscribing in constructors is fairly bad practice, 
    // although you can get away with it in singleton services
    wsService.connect(url).pipe(
      // map responses to statuses
      map((response: MessageEvent): Status => {
        let data = JSON.parse(response.data);
        return data;
      })
    ).subscribe((status: Status) => {
      // send the status to all subscribers
      this.subject.next(status);
    });
  }

  getObs(): Observable<Status> {
    return this.subject.asObservable();
  }

  sendMsg(msg): void {
    this.subject.next(msg);
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.