0

I have successfully displayed my playlist but I would like to add the number of videos to each playlist.

For that I have to send another request. I can't merge the number of videos in my playlist result

Thank you for your help, 3 days without results

My yt.service.ts

  getPlaylistsForChannel(channel): Observable<any[]> {
    return this.http
      .get<any[]>(
        "https://www.googleapis.com/youtube/v3/playlists?key=" +
          this.apiKey +
          "&channelId=" +
          channel +
          "&part=snippet,id&maxResults=20"
      )
      .pipe(
        catchError(err => of([])),
        map(res => {
          return res["items"];
        })
      );
  }

  getListVideos(listId): Observable<any[]> {
    console.log(listId);
    return this.http
      .get<any[]>(
        "https://www.googleapis.com/youtube/v3/playlistItems?key=" +
          this.apiKey +
          "&playlistId=" +
          listId +
          "&part=snippet,id&maxResults=20"
      )

      .pipe(
        catchError(err => of([])),
        map(res => {
          console.log(res["items"]);
          return res["items"];
        })
      );
  }

my playlists.ts

  searchPlaylists() {
    this.playlists = this.ytService.getPlaylistsForChannel(this.channelId);
    let that = this;
    this.playlists = this.playlists.pipe(
      catchError(err => of([])),
      mergeMap(res => {
        let nb = res.length;
        for (let i = 0; i < nb; i++) {
          that.ytService.getListVideos(res[i].id).pipe(
            map(res2 => {
              res.number = res2.length;
            })
          );
        }
        console.log(res);
        return res;
      })
    );
  }
kai
  • 6,702
  • 22
  • 38
Shmuel
  • 11
  • 1

1 Answers1

0

I think I understand what you're trying to do and we will get there, but let's take things from the beginning.

First of all you can avoid the:

let that = this;

by using arrow functions:

searchPlaylists = () => {

Also try to use meaningful variable name that are easier for someone, who has never seen your code before, understand what's going on. Let's write it a little bit clearer:

lists: any[];

searchPlaylists = () =>
  this.ytService
    .getPlaylistsForChannel(this.channelId)
    .pipe(
      catchError((err) => of([])),
      mergeMap((playlists) =>
        playlists.map(async (playlist) => {
          const videoList = await this.ytService
            .getListVideos(playlist.id)
            .toPromise();

          return { ...playlist, number: videoList.length };
        })
      )
    )
    .subscribe((updatedLists) => (lists = updatedLists));

Things to remember:

  • You got to subscribe to see the value changes and then you must assign those values
  • You got to be careful on WHEN you check things that are running async and when you are expecting these to be assigned
  • You need to get familiar with the ES6 syntax and the RXJS operators
  • The client should not handle that kind of logic. This can't scale. In case the number of playlists becomes huge, the number of HTTP calls will be just too much

Also pay attention to the answer by @kai where he suggests different RXJS operators. It might seem more complex but the result will be even cleaner

Antonis
  • 647
  • 6
  • 15