Search code examples
angularrxjsbehaviorsubjectsubject-observer

Difference between Subject (being a special case of Observable) and Observable


According to the docs on Subject, it's a special case of Observable that lets all the observers share a common execution path. The example shows that each observer gets the same emitted values after it's subscribed to the source.

I'm not entirely clear on how it differs from a case of a plan Observable emitting values. Every one of the multiple subscribers will receive each next'ed value. The values that have been emitted prior to respective subscription aren't delivered (unless we have pipe'ed in some shareReply'ing of those explicitly).

What's the actual difference making Subject a special case of Observable? I'm missing the obvious, possibly.


Solution

  • An observable, by definition is a data producer.

    A Subject on the other hand can act as both – a data producer and a data consumer.

    This implies two things.

    1. A subject can be subscribed to, just like an observable.
    2. A subject can subscribe to other observables.

    That being said, there is one critical difference between a subject and an observable.

    All subscribers to a subject share the same execution of the subject. i.e. when a subject produces data, all of its subscribers will receive the same data. This behavior is different from observables, where each subscription causes an independent execution of the observable.

    Example:

      // Here a subject is acting like a data producer
      const subject = new Subject();
      const subjObserv = subject.asObservable();
      subjObserv.subscribe((data: number) => console.log("subect A " + data));
    
      for (let i = 1; i <= 5; i++) subject.next(i);
    
      subjObserv.subscribe((data: number) => console.log("subect B " + data));
      subject.next(6);
    
    
      // simple observer
      const plainObs = Observable.of([1, 2, 3, 4, 5]);
      plainObs.subscribe(data => console.log("plain onservable A " + data));
      plainObs.subscribe(data => console.log("plain onservable B " + data));
    

    Output:

    subect A 1
    subect A 2
    subect A 3
    subect A 4
    subect A 5
    subect A 6
    subect B 6
    plain onservable A 1,2,3,4,5
    plain onservable B 1,2,3,4,5
    

    As you can notice we get the output as many times as we subscribe plainObs but for the subjObserv we get output that are emitted after subscription.