9

I am learning Angular2 by this official cookbook.

The below code just appears out of sudden. Why "missionAnnounced$" doesn't have a variable declaration? let missionAnnounced$ = ... What is the logic of the below code?

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
@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);
  }
}
user3743222
  • 18,345
  • 5
  • 69
  • 75
Nicolas S.Xu
  • 13,794
  • 31
  • 84
  • 129
  • 2
    https://github.com/Reactive-Extensions/RxJS – zerkms Oct 30 '16 at 03:42
  • I realize this is a 2 year-old closed post, but just in case someone else also landed here: the line `missionAnnounced$ = this.missionAnnouncedSource.asObservable();` is actually a property (of the MissionService class) declaration & initialization; same as the `missionConfirmed$ ` line and the two private lines above it. – Nagi Oct 22 '18 at 09:12

2 Answers2

21

An Observable only allows for subscribing, while a Subject allows for both publishing and subscribing (a subject is an observable). So using a Subject allows your service to be used as both a publisher and a subscriber.

@Component({})
class ComponentOne {
  constructor(private service: MissionService) {}

  onClick() {
    service.announceMission('mission started');
  }
}

@Component({})
class ComponentTwo {
  constructor(private service: MissionService) {
    service.missionAnnounced$.subscribe(mission => console.log(mission))
  }
}

@Component({})
class ComponentThree {
  constructor(private service: MissionService) {
    service.missionAnnounced$.subscribe(mission => console.log(mission))
  }
}

Now every one that wants to subscribe to the mission announced event can just subscribe. The ComponentOne will be the one emitting the mission announced event.

Why "missionAnnounced$" doesn't have a variable declaration?

It does. missionAnnounced$ is the variable name, being assigned the Subject in its observable form. Class member variables don't use let

What is the logic of the below code?

Subscribers subscribe to the observables (the $ variables), while publishers call the announceMission and confirmMission. All subscribers to missionAnnounced$ and missionConfirmed$, respectively, will receive those events.

ShellZero
  • 4,415
  • 12
  • 38
  • 56
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
4

To complement the previous answer, you will find ample details in the following SO link : What are the semantics of different RxJS subjects?

In short, an Rxjs subject implements both the Observable, and the Observer interface (see the link for more details about the different flavours and behaviours of subject). The standard subject used here acts as a pipe, and pass through its Observable interface all the values it receives on its Observer interface. The asObservable function call that you see in the code hides the implementation of the Observer interface, so you cannot inadvertently use it when you are not supposed too, i.e. you can then only use this subject as you use any regular observable.

Community
  • 1
  • 1
user3743222
  • 18,345
  • 5
  • 69
  • 75