Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between using a Subject and an Observable, and what are the uses for each?

I have learned of two different ways of making an Observable. First one was with a Subject, like so:

// file A
const message$ = new Subject();

// file B
message$.subscribe( (message) => console.log(message) );

// file C
message$.next("Hello there!");

This method of creating an Observable allows me to have a way to exchange data from file B to file C.

The second way is via the Observable class, like so:

// file A
const click$ = new Observable( function(observer) { 
  //Alternatively, I can use Observable.create()
  document.addEventListener('click', (e) => observer.next(e));
});

// file B
click$.subscribe( (cl) => console.log(cl) );

The main difference that I can gather between the Subject way and the Observable way is that I am not sure how to have some sort of communication between some file C, to the subscribers of the Observable. Basically, click$ does not have a .next() method, and the observer methods are in the function that we pass to the observable.

Other than this difference in behavior, is there another difference between observables made with Subject, and those made with Observable

like image 328
Sammy I. Avatar asked Aug 25 '18 05:08

Sammy I.


3 Answers

A Subject is both Observable and Observer at the same time. That makes it so tempting to use, because you get a reference to an Observer that you can pass around in your code and emit items from wherever you want. However, that increases the error-proneness of your code by a lot, as you switch from a declarative definition of your Observable to a imperative one.

Generally speaking, you should use Observable creation functions (of, from, create) wherever possible. I'd say most cases can be solved without Subjects. There is a steep learning-curve though, as you must get to know most of the Observable creation functions in order to follow that pattern.

Subject might come more natural to developers who are used to code imperatively (that is: with a script language like JS), as it kind of resembles a simple wrapper object for a callback function. And one might ask, why is there a Subject anyway if its not desirable.

According to this article, Subjects are to be used in one case only:

To generate a hot observable imperatively and statefully, without any direct external source.

In short, that means: Use Subject when you don't have any external source (like an Observable, Promise or Event) and need to multicast the state of a class from inside a function. You shouldn't expose that Subject to others, though!

I suggest reading this article to you, it will clear up things.

like image 142
ggradnig Avatar answered Oct 19 '22 23:10

ggradnig


Subject implements both the Observable and the Observer interface.

Implementing the Observable interface means, among other things, that you can subscribe to a Subject.

Implementing the Observer interface means, among other things, that with a Subject you can call the methods next error and complete.

You create Observables using Subject in the case you want to control programmatically the flow of events of that Observable, which is the case you mentioned of managing communication between C and B.

like image 38
Picci Avatar answered Oct 19 '22 23:10

Picci


The relation between Subject and Observable goes like this:

class Observable {}

class Subject extends Observable {}

Subject implements Subscriber interface. So you can use Subject as a Subscriber (Observable cannot be used like this):

const subj = new Subject()
observable.subscribe(subj)

Subject can hide it's Subscriber interface by calling asObservable method - turning Subject into plain Observable;


I generally use Subject when my code is going to generate events and I use Observable when I already have some source of events

For example using Subject as a queue:

const queue = new Subject();

queue.pipe(
  concatMap(doStuff)
).subscribe()

queue.next('do this')
queue.next('do that')

or using Subject as a signaller to stop other Observable

const stop = new Subject();

someObservable.pipe(
  map(x => x + 1)
  takeUntil(stop)
)

// somewhere in my code
stop.next()

Other than this difference in behavior, is there another difference between observables made with Subject, and those made with Observable

I wouldn't say there are differences - It is more like Subject is a complement to plain Observable - allowing us to do more things when needed.

like image 29
m1ch4ls Avatar answered Oct 19 '22 23:10

m1ch4ls