Angular 8 - подписаться на один сервис из двух разных компонентов - PullRequest
0 голосов
/ 09 марта 2020

У меня есть сервис angular и два разных несвязанных компонента, которые используют этот сервис:

Код сервиса:

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 - после подписки

Может кто-нибудь объяснить, в чем проблема is?

Примечание. Я добавил свою услугу поставщикам модулей и получил тот же результат.

Спасибо.

вот код для webSocketService: https://github.com/elliotforbes/ng-chat/blob/master/src/app/common/services/websocket.service.ts

Ответы [ 2 ]

1 голос
/ 09 марта 2020

Вы должны взять под контроль свои собственные предметы, вместо того, чтобы использовать 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);
  }
}
1 голос
/ 09 марта 2020

Вы можете использовать Поведенческий субъект вместо обычного.

https://medium.com/@luukgruijs / creation-rx js -behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

...