ritz078
ritz078

Reputation: 2337

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.

Upvotes: 7

Views: 9539

Answers (1)

Harry Ninh
Harry Ninh

Reputation: 16718

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();

Upvotes: 14

Related Questions