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