Angular 亲子交流使用服务?

Angular parent and children communication using a service?

我已经开始学习 Angular,并且我 运行 从 official docs 学习这个关于使用服务的父服务通信的例子:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}

我对这部分有点困惑:

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

我知道 .asObservable() 以这个 Subject 作为源创建了一个新的 Observable。但是,为什么我们需要它? missionAnnouncedSource 已经是可观察的。 我们为什么不简单地提供这样的服务:

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable()
export class MissionService {

  // Observable string sources
   missionAnnouncedSource = new Subject<string>();
   missionConfirmedSource = new Subject<string>();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}

当然,我需要调整组件中的代码才能使其正常工作,但我没有发现任何问题:

  //astronaut.component.ts

  constructor(private missionService: MissionService) {
    this.subscription = missionService.missionAnnouncedSource.subscribe(
      mission => {
        this.mission = mission;
        this.announced = true;
        this.confirmed = false;
    });
  }

这是某种约定还是我遗漏了什么?

不需要 它,但想法是,如果您只公开一个可观察对象,就不可能 next public变量 - 它只能在服务中完成。

你的问题给我同样的疑惑。所以我调查了一下。这是我发现的:

来自 RxJS docs

A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.

所以你可以做同样的事情,只是 Observable 不能通过 next(value) 调用修改值。

这个 article 非常好,解释了您对 最佳实践 的疑问,这个例子来自那里:

In the RxJS world it's considered best practice to only expose Subjects to the parts of your application that would add new data into the Observable sequence. This is the same idea behind only allowing write access to certain parts of your application, private and public class members, etc.

To create an Observable from a Subject, you can simply invoke asObservable on any Subject:

let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();

We now have a new variable called currentUser$ that is an Observable of currentUserSubject$'s observable sequence. To see how this works, lets subscribe to the currentUser observable and then add some data to the currentUserSubject$:

let currentUserSubject$ = new BehaviorSubject() < string > 'Eric';
let currentUser$ = currentUserSubject$.asObservable();

currentUserSubject$.subscribe(val => {
  console.log(val);
});
// => 'Eric'

currentUserSubject$.next('hello');
// => 'hello'

Note that if you try and call currentUser$.next(), it will throw an error because Observables can only observe a sequence - thus providing you with read-only access to the currentUserSubject!