Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between Observable and a Subject in rxjs?

I was going through this blog and reading about Observables and couldn't figure out the difference between the Observable and a Subject.

like image 276
Lijin Durairaj Avatar asked Nov 28 '17 17:11

Lijin Durairaj


People also ask

What is the difference between Observable and subject and BehaviorSubject?

Observable is a Generic, and BehaviorSubject is technically a sub-type of Observable because BehaviorSubject is an observable with specific qualities. An observable can be created from both Subject and BehaviorSubject using subject.

What is difference between Observable and subscribe?

Observables are not executed until a consumer subscribes. The subscribe() executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.

What is difference between Observable and Observer?

Observer : Any object that wishes to be notified when the state of another object changes. Observable : Any object whose state may be of interest, and in whom another object may register an interest.

What is Observable in RxJS?

RxJS introduces Observables, a new Push system for JavaScript. An Observable is a Producer of multiple values, "pushing" them to Observers (Consumers). A Function is a lazily evaluated computation that synchronously returns a single value on invocation.


10 Answers

In stream programming there are two main interfaces: Observable and Observer.

Observable is for the consumer, it can be transformed and subscribed:

observable.map(x => ...).filter(x => ...).subscribe(x => ...)

Observer is the interface which is used to feed an observable source:

observer.next(newItem)

We can create new Observable with an Observer:

var observable = Observable.create(observer => { 
    observer.next('first'); 
    observer.next('second'); 
    ... 
});
observable.map(x => ...).filter(x => ...).subscribe(x => ...)

Or, we can use a Subject which implements both the Observable and the Observer interfaces:

var source = new Subject();
source.map(x => ...).filter(x => ...).subscribe(x => ...)
source.next('first')
source.next('second')
like image 184
ZahiC Avatar answered Oct 12 '22 02:10

ZahiC


Observables are unicast by design and Subjects are multicast by design.

if you look at the below example - each subscription receives the different values as observables developed as unicast by design.

import {Observable} from 'rxjs';

let obs = Observable.create(observer=>{
   observer.next(Math.random());
})

obs.subscribe(res=>{
  console.log('subscription a :', res); //subscription a :0.2859800202682865
});

obs.subscribe(res=>{
  console.log('subscription b :', res); //subscription b :0.694302021731573
});

this could be weird if you are expecting the same values on both the subscription.

we can overcome this issue using Subjects. Subjects is similar to event-emitter and it does not invoke for each subscription. consider the below example.

import {Subject} from 'rxjs';

let obs = new Subject();

obs.subscribe(res=>{
  console.log('subscription a :', res); // subscription a : 0.91767565496093
});

obs.subscribe(res=>{
  console.log('subscription b :', res);// subscription b : 0.91767565496093
});

obs.next(Math.random());

both the subscription are got the same output value!.

like image 25
jaibalaji Avatar answered Oct 12 '22 00:10

jaibalaji


Observables

  1. They are cold: Code gets executed when they have at least a single observer.

  2. Creates copy of data: Observable creates copy of data for each observer.

  3. Uni-directional: Observer can not assign value to observable(origin/master).

  4. The code will run for each observer . If its a HTTP call, it gets called for each observer.

  5. if its a service we want to share among all the components, it wont have latest result all new subscribers will still subscribe to same observable and get value from scratch

  6. Unicast means can emit values from the observable not from any other component.

Subject

  1. They are hot: code gets executed and value gets broadcast even if there is no observer.

  2. Shares data: Same data get shared between all observers.

  3. bi-directional: Observer can assign value to observable(origin/master).

  4. If are using using subject then you miss all the values that are broadcast before creation of observer. So here comes Replay Subject

  5. multicast, can cast values to multiple subscribers and can act as both subscribers and emmitter

like image 35
jaideep Avatar answered Oct 12 '22 00:10

jaideep


I found the accepted answer slightly confusing!

An Observer isn't the interface for feeding an Observable source, it's the interface for observing an Observable source... which makes more sense from the name, right?

So, the reason that:

var observable = Observable.create(observer => { 
    observer.next('first'); 
    observer.next('second'); 
    ... 
});

works - creating an observable which emits 'first' then 'second' - is that the argument to Observable.create(...) is a subscribe function, it basically defines which Observer events will happen on a direct Observer of that Observable.

If you want to go into it a little bit further again, it's important to understand that the subscribe function isn't directly called on the Observer object when you subscribe, instead it's mediated by a Subscription object which can enforce correct observable rules, e.g. that an Observable will never emit a new value after observer.complete() has been called, even if your subscribe function looks as if it would.

REF: http://reactivex.io/rxjs/manual/overview.html#creating-observables

A Subject is both an Observable and an Observer and once again it looks just like the Observer interface is the way to 'feed' events to the Subject. But it's easier to understand the naming if you realise that a Subject is a bit like an Observable with the equivalent of the subscribe function (i.e. where you define what events will happen to things observing it) sitting there right on the object, even after it has been created. So, you call Observer methods on the Subject to define what Observer events will happen on things observing it! 😊 (And again, there are intermediate objects involved, to make sure that you can only do legal sequences of things.)

REF: http://reactivex.io/rxjs/manual/overview.html#subject

like image 27
MikeBeaton Avatar answered Oct 12 '22 00:10

MikeBeaton


Observable can inform only one observer, while Subject can inform multiple observers.

like image 37
Mehul Jain Avatar answered Oct 12 '22 02:10

Mehul Jain


See rxjs document (more information and examples there): http://reactivex.io/rxjs/manual/overview.html#subject

What is a Subject? An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.

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

and code, Subject extending Observable: https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22

/**
 * @class Subject<T>
 */
export class Subject<T> extends Observable<T> implements SubscriptionLike {
//...
}
like image 45
John Smith Avatar answered Oct 12 '22 02:10

John Smith


Imagine if you have a stream of data coming into your application like in a websocket connection. You want a way to handle it. There is a few solution:

1. normal ajax request: This solution is not viable because it is not applicable to process push data. It is more of a pull then a push.

2. Promise: Also not good because you have to trigger them and they can only retrieve once. Also more of a pull then a push.

So in order to retrieve this data, in the old time, we do a long-polling. Which is where we set an interval function to retrieve that stream of data every 1 minute for an example. Though it works, it actually burdening resources like CPU and memory.

But now with option no 3,

3. Observable: You can subscribe and let the stream of data to come in non-stop until the function complete has been called.

Cool right ? But then there is another problem. What if you want to observe incoming data only once somewhere in your application. But you want to use that data simultaneously around your application when the data arrived. That is when and where you use Subject. You place subject.subscribe() at places you want to use throughout your application. When the data arrived, places where there is subject.subscribe() will process them simultaneously. But the observer must subscribe with the subject as its argument like this.

observer.subscribe(subject).

Example application is when you want to build a notification alert.

You cannot have multiple subscription of the same observable because chances are, each subscribers will received different input data. But with subject, all that subscribe() through subject will be retrieving the same data.

Another analogy is through magazine subscription. Each subscribers will received the magazine with their name on it. So, different subscription = different receiver name.(Normal Observable) But when you share with your friends, all of your friend would receive the same magazine with only your name on it.(Normal Observable with Subject)

This guy explain it very well with code example. You can check it out at https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

Hopefully this answer helps.

like image 26
Apit John Ismail Avatar answered Oct 12 '22 00:10

Apit John Ismail


Briefly,

subject: you can send to it and receive from it.

Observable: you can receive from it only.

In another words, In subject you can subscribe to it and you can use it to broadcast to other subscribers any time and anywhere in code.

whilst, in observable you can subscribe to it only (you can't use it to broadcast data after it have been initialized). The only place you can broadcast data from observable is inside its constructor.

like image 30
Manar Gul Avatar answered Oct 12 '22 02:10

Manar Gul


From another perspective, it is good to note that the subscription to an Observable re-execute the Observable function. This can lead performance issue if the data source is a service for instance.

If you want several subscribers to get the same value, you may need a Subject. For this, make sure that your subscription is set before the Subject subscribed to the data source. Otherwise, your process would be stuck.

More details here: https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

like image 23
Vince Avatar answered Oct 12 '22 00:10

Vince


Observable: Only the Observable knows how and when the events are triggered on the observable. i.e the next() method has to be called only inside the instantiated constructor. Also, on subscribing each time, a separate observer is created and calls next() method using particular observer inside constructor only, in the following example subscriber itself is the observer and it is subscribed when the instantiated constructor gets executed. Ex:

import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  setTimeout(() => {
    subscriber.next(3);        
  }, 1000);
});

Subject: Here next() method can be used by subject anywhere outside the constructor. Also, when next() method is called before subscribing, the particular event will be missed. Hence next() method has to be called only after subscribing. Ex:

import { Subject } from 'rxjs';
 
const subject = new Subject<number>();
 

subject.next(1); // this is missed
subject.subscribe({
  next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
  next: (v) => console.log(`observerB: ${v}`)
});     
subject.next(2);
like image 39
mukhtar alam Avatar answered Oct 12 '22 01:10

mukhtar alam