Возврат значений зацикленного API с использованием Observables в Angular - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь получить цикл для возврата вызова API.Используя Spotify API, я могу сгенерировать идентификатор исполнителя по имени, поэтому ранее в коде я создал список имен, содержащийся в массиве.В целях тестирования я использую фиктивный массив с теми же значениями, что и предыдущий вызов API.

  getAllSpotifyArtistIds(){
    let dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
    for (let i = 0; i < dummyArtistList.length; i++) {
      this.artistToQuery = dummyArtistList[i];
      this.generateArtistIdFromArtist(dummyArtistList[i]).subscribe((response) => {
      this.newProperty.push(response); //this is a class property I'm hoping to populate with this response.
      })
    }
  }

функция generateArtistIdFromArtist (artistName: string) при каждом вызове возвращает одно значение - идентификатор исполнителя, запрашиваемый из API Spotify.

Код для создания идентификатора Arist изspotify выглядит следующим образом:

  generateArtistIdFromArtist(artistName){
    return this.spotifyService.getToken().pipe( 
      flatMap((accessTokenResponse) => {
        return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token)
        .map((response) => {
          response.artists.items.forEach((spotifyArtist) => {
            this.spotifyArtistListFromQuery.push(spotifyArtist.name);
          });
          const artistMatchIndexPosition = this.spotifyArtistListFromQuery.findIndex((artistToQueryNow) => {
            return artistToQueryNow === artistName;
          });
          //Spotify returns multiple artists with similar names, so check for identical match
          if (artistMatchIndexPosition >= 0 ){
             this.artistIdListFromSpotify.push(response.artists.items[artistMatchIndexPosition].id)
             return response.artists.items[artistMatchIndexPosition].id;
                // finally return the id of the artist if there's a match
          }
        });
      })
    );
  }

Я пытался поместить setTimeout () в различные места, но я думаю, что я просто недостаточно хорошо понимаю асинхронное кодирование, чтобы действительно знать, что яделает.Я подумал, что, возможно, форсирование некоторых пауз может позволить петле наверстать упущенное.На данный момент я получаю только 3 значения.

Я ожидаю, что результаты Spotify будут возвращены для каждого исполнителя в dummyArtistList, но он возвращает только несколько значений, и они как-то неверны.

Это прекрасно работает, если вы передаете ему одно имя, но цикл завершается ошибкой, если вы начинаете делать больше, чем один, а на трех он дает совершенно неправильные результаты.Я новичок в кодировании и особенно в асинхронности, поэтому мне трудно понять, почему я не могу заставить цикл ждать завершения вызова API с помощью наблюдаемых.Я уверен, что это как-то связано с тем фактом, что сам цикл не является асинхронным, а вызов API - любая помощь в сортировке, которая будет очень полезна.

Ответы [ 3 ]

0 голосов
/ 07 февраля 2019

Вы также можете сделать это, используя forkJoin , потому что вы хотите, чтобы все результаты были в массиве.

Сохраните все свои observables во временном массиве и подпишитесь на него, используя forkJoin operator

getAllSpotifyArtistIds(){
    let dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
    let artistSet = [];
    for (let i = 0; i < dummyArtistList.length; i++) {
      this.artistToQuery = dummyArtistList[i];
      artistSet.push(this.generateArtistIdFromArtist(dummyArtistList[i]))
    }
     forkJoin(...artistSet).subscribe((response) => {
          //Here response is an array and you can simply assign
          this.newProperty = response;
     })
  }
0 голосов
/ 07 февраля 2019

Благодаря помощи @ Ritesh я смог понять, как решить эту проблему.

Последние две функции:

  generateArtistIdFromArtist(artistName) {
      return this.spotifyService.getToken().pipe(
        flatMap((accessTokenResponse) => {
          return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token);
               })
      );
  }

, а затем, возвращая массив информации, содержащей исполнителей, используя этот вызов, сам APICallArray фактически имел эту информацию, очевидно, не нужно подписываться.Я до сих пор не до конца понимаю, что это дает, но я могу получить ответы на все вопросы.

  getAllSpotifyArtistIds() {
    const APICallArray = [];
    const dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];
    const ArtistOutputArray = [];
    for (let i = 0; i < dummyArtistList.length; i++) {
      this.artistToQuery = dummyArtistList[i];
      APICallArray.push(this.generateArtistIdFromArtist(dummyArtistList[i]));
    }

    for (let i = 0; i < APICallArray.length; i++) {
        APICallArray[i].subscribe((response) => {
          ArtistOutputArray.push(response);
        });
    }
    return ArtistOutputArray;
  }

Спасибо @Ritesh!

0 голосов
/ 07 февраля 2019

Вам нужен массив наблюдаемых, оператор concat из rxjs и подписка на него.Подробнее о concat здесь .

Вы можете импортировать concat следующим образом:

import {concat} из 'rxjs / operator';

  getAllSpotifyArtistIds() {
    const APICallArray = [];
    const dummyArtistList = ['loren north', 'Randy Emata', 'Dyekho', 'The Lemon Twigs', 'The Toasters'];

    for (let i = 0; i < dummyArtistList.length; i++) {
        this.artistToQuery = dummyArtistList[i];
        APICallArray.push(this.generateArtistIdFromArtist(dummyArtistList[i]));
     }
     concat(...APICallArray).subscribe((res) => {
         res.map((response) => {
            response.artists.items.forEach((spotifyArtist) => {
              this.spotifyArtistListFromQuery.push(spotifyArtist.name);
            });

            const artistMatchIndexPosition = this.spotifyArtistListFromQuery.findIndex((artistToQueryNow) => {
                return artistToQueryNow === artistName;
            });
            if (artistMatchIndexPosition >= 0 ) {
                this.artistIdListFromSpotify.push(response.artists.items[artistMatchIndexPosition].id);
                this.newProperty.push(response.artists.items[artistMatchIndexPosition].id);
            }
        });
     });
}

  generateArtistIdFromArtist(artistName) {
        return this.spotifyService.getToken().pipe(
          flatMap((accessTokenResponse) => {
            return this.spotifyService.searchArtistID(artistName, accessTokenResponse.access_token);
                 })
        );
    }
...