6/6/19

When You Should Use Subject

Subject - Who are you?

Yes, lot of us (angular people) have heard about subjects. Yes, it is something that acts like observable (you can subscribe to it):


const subject = new Subject();
...
subject.subscribe(x => console.log(x));

And simultaneously you also can call "next" method, like in observer:

 ...
 const button = document.querySelector('button')
 button.addEventListener("click", () => subject.next('click')); 
 ...

Ok, great, but... when it is good practice to use this Subject thing? you may ask...

Lets look on what Angular guys are Doing

Everybody who starts with "get started" section of angular - knows about "heroes tour" tutorial.
Quick search shows the use of "Subject" in the HeroSearchComponent.
Here you have a pretty common scenario: a search input which have to trigger a search request and populate with response results a list below the input...
So in "input" event handler you expect to see something like this:


  search(term: string): void {
    this.heroService.searchHeroes(term).subscribe(results => this.heroes = results);
  }

Or, when displaying the data using "Async" pipe, something like:

/*    
   <li *ngFor="let hero of heroes$ | async" >
      <a routerLink="/detail/{{hero.id}}">
        {{hero.name}}
      </a>
    </li>
*/
  search(term: string): void {
    this.heroes$ = this.heroService.searchHeroes(term);
  }

The problem with this code (although it will work) - is that the subscription to "searchHeroes" method is done each time when search terms changes, (not mention is already done at "ngOnInit" lifehook of the component):

 ngOnInit(): void {
    this.heroes$ = this.searchTerms.pipe( // pipe is the equivalent of "subscribe"
      // wait 300ms after each keystroke before considering the term
      debounceTime(300),

      // ignore new term if same as previous term
      distinctUntilChanged(),

      // switch to new search observable each time the term changes
      switchMap((term: string) => this.heroService.searchHeroes(term)),
    );
  }

And it is bad to subscribe multiple times, because of memory leaks potential. Instead - by using searchTerms Subject(like Angular guys did), you can call the "next" and trigger the service again, which is much more accurate:

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
  }
 

No comments:

Post a Comment

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...