Home > Mobile >  Can I concatentate the result of Observables?
Can I concatentate the result of Observables?

Time:12-12

Using the Hero example from angular.io:

/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable<Hero[]> {
  if (!term.trim()) {
    // if not search term, return empty hero array.
    return of([]);
  }
  return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
    tap(x => x.length ?
       this.log(`found heroes matching "${term}"`) :
       this.log(`no heroes matching "${term}"`)),
    catchError(this.handleError<Hero[]>('searchHeroes', []))
  );
}

How can I change this so that any searchable attribute of a Hero is captured with this search? For example, suppose address is a searchable attribute, so that:

this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`)

works fine.

I tried this modification:

/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable<Hero[]> {
  if (!term.trim()) {
    // if not search term, return empty hero array.
    return of([]);
  }
  var names = this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
    tap(x => x.length ?
       this.log(`found heroes matching "${term}"`) :
       this.log(`no heroes matching "${term}"`)),
    catchError(this.handleError<Hero[]>('searchHeroes', []))
  );
  var addresses = this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`).pipe(
    tap(x => x.length ?
       this.log(`found heroes matching "${term}"`) :
       this.log(`no heroes matching "${term}"`)),
    catchError(this.handleError<Hero[]>('searchHeroes', []))
  );
  return names   addresses;
}

But this doesn't work at all because the result of the http GET is an Observable, not a string. However, the type or kind of result in each case is the same thing (a Hero), so I ought to be able to implement something like this, right?

Before you ask, I know I really ought to modify the API this function is calling to do something like this:

this.http.get<Hero[]>(`${this.heroesUrl}/?searchable=${term}`)

where searchable is any searchable Hero attribute, but I can't modify API at this time (and I will in the future). For now, can I implement this hack? How can I concatenate the result of Observables?

CodePudding user response:

Use the forkJoin operator:

searchHeroes(term: string): Observable<Hero[]> {
...
  return forkJoin({
     names: this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`),
     addresses: this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`)
  }).pipe(map(({ names, addresses}) => names.concat(addresses));
}

  • Related