Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switchMap: Multiple (2) requests getting triggered

I am using Angular 2 RC-4. I am trying to make a network request whenever there is a change in the input box. But the request is getting called twice.

My code looks like:

component.ts

this.term = new Control();

this.suggestions = this.term.valueChanges
      // .debounceTime(1000)
      // check if the search term's length is >= 1
      .filter(term => term && term.length)

      // switchMap only subscribes to one observable at a time so if a new key is
      // pressed before the response of previous request has been recieved, it
      // automatically un-subscribes from the previous observable thus cancelling the previous
      // request.
      .switchMap(term => this._suggestionsService.getSuggestions(term, uuid))

component.html

<ul [hidden]='!(suggestions | async)?.length'>
<li *ngFor='let suggestion of suggestions | async'>{{suggestion.name}}</li>
</ul>

suggestion.service.ts

getSuggestions(term){
 return this.http.get('some-url')
      .map((res: Response) => res.json());
}

This makes the network request 2 times. But if I change the code in component slightly and manually subscribe instead of using async pipe, the network request is only made once.

component.ts

this.term.valueChanges
  .filter(term => term && term.length)
  .switchMap(term => this._suggestionsService.getSuggestions(term, uuid))
  .subscribe(value => this.suggestions = value);

component.html

<ul [hidden]='!suggestions.length'>
<li *ngFor='let suggestion of suggestions'>{{suggestion.name}}</li>
</ul>

Results are fine in both. Only the number of network requests is my concern. I guess there is some concept about observables that I am missing.

like image 319
ritz078 Avatar asked Aug 03 '16 22:08

ritz078


1 Answers

The problem is that there are 2 async in the template that causes the observable to be subscribed multiple times and hence the request is made 2 times.

Using share will do the trick:

this.suggestions = this.term.valueChanges
    .filter(term => term && term.length)
    .switchMap(term => this._suggestionsService.getSuggestions(term, uuid))
    .share();
like image 74
Harry Ninh Avatar answered Nov 10 '22 02:11

Harry Ninh