Home > other >  Chaining map within a RxJS Pipe does not work
Chaining map within a RxJS Pipe does not work

Time:09-10

I'm trying to transform a GET request from the YouTube Search API with the following function.

The first map should get me the items within the response Object. With the second map I want to map the items to my Custom Class SearchResult. But for some reason there is always the complete list of items within the the second map, instead of iterating over the single Elements. And as a result the pipe won't return an Observable with an Array of SearchResult Elements.

Angular 13 RxJS 7.5

  search(query: string) : Observable<SearchResult[]>{
    const params: string = [
      `q=${query}`,
      `key=${this.apiKey}`,
      `part=snippet`,
      `type=video`,
      `maxResults=10`
    ].join('&');
    const queryUrl = `${this.apiUrl}?${params}`;
    return this.http.get(queryUrl).pipe(
      map((response : any) => response.items),
      map(item => {
        return new SearchResult({
          id: item.id.videoId,
          title: item.snippet.title,
          description: item.snippet.description,
          thumbnailUrl: item.snippet.thumbnails.high.url
        });
      }),
    )}
  }

CodePudding user response:

Since your property is an array, you need to map each array element to a new SearchResult:

return this.http.get(queryUrl).pipe(
  map((response : any) => response.items),
  map(items => items.map(item => {
    return new SearchResult({
      id: item.id.videoId,
      title: item.snippet.title,
      description: item.snippet.description,
      thumbnailUrl: item.snippet.thumbnails.high.url
    });
  })),
)}

CodePudding user response:

The first map returns the items array from the response, and the second one should use the Array.map() function to map the array items to the required model.

The RxJS's map operator doesn't iterate through the array items, instead, it maps each value emitted in the stream to something else.

You can handle like the following:

search(query: string): Observable<SearchResult[]> {
  const params: string = [
    `q=${query}`,
    `key=${this.apiKey}`,
    `part=snippet`,
    `type=video`,
    `maxResults=10`,
  ].join('&');
  const queryUrl = `${this.apiUrl}?${params}`;
  return this.http.get(queryUrl).pipe(
    map((response: any) => response.items),
    map((items) =>
      items.map(
        (item) =>
          new SearchResult({
            id: item.id.videoId,
            title: item.snippet.title,
            description: item.snippet.description,
            thumbnailUrl: item.snippet.thumbnails.high.url,
          })
      )
    )
  );
}

You can read more about it here: https://rxjs.dev/api/operators/map

  • Related