首页 > 解决方案 > 在 Angular 中使用 Observables 返回循环的 API 调用值

问题描述

我试图让一个循环返回一个 API 调用。使用 Spotify API,我可以从名称中生成艺术家的 id,因此在前面的代码中,我生成了一个名称列表,保存在一个数组中。出于测试目的,我使用了一个虚拟数组,该数组与之前的 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) 每次调用都会返回一个值,即从 Spotify 的 API 中查询的艺术家 ID。

从 spotify 生成 Arist ID 的代码如下:

  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 个值。

我希望 dummyArtistList 中的每个艺术家都会返回 Spotify 结果,但它只返回一些,而且它们在某种程度上是不正确的。

如果您将单个名称传递给它,这将非常有效,但是如果您开始执行多个名称,则循环失败,并且在三个上它会给出完全错误的结果。我是编码新手,尤其是异步,所以我很难理解为什么我不能让循环等待 API 调用完成 observables。我确信这与循环本身不是异步的事实有关,并且 API 调用是,任何帮助解决这个问题将不胜感激。

标签: angularapiasynchronousrxjsobservable

解决方案


您也可以使用forkJoin来执行此操作,因为您希望将所有结果都放在一个数组中。

将所有内容保存在一个临时数组中并使用运算符observables订阅它forkJoin

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

推荐阅读