【问题标题】:Returning looped API call values using Observables in Angular在 Angular 中使用 Observables 返回循环的 API 调用值
【发布时间】:2019-02-07 06:45:11
【问题描述】:

我正在尝试获取一个循环来返回 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 调用是,任何帮助解决这个问题将不胜感激。

【问题讨论】:

    标签: angular api asynchronous rxjs observable


    【解决方案1】:

    您也可以使用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;
         })
      }
    

    【讨论】:

      【解决方案2】:

      你需要的是一个可观察的数组,来自 rxjs 的 concat 运算符并订阅它。阅读更多关于 concat here.

      你可以像这样导入 concat:

      从 'rxjs/operators' 导入 { concat };

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

      【讨论】:

      • 有意思,我现在就试试!
      • 我在 src/app/home/home.component.ts(118,31) 中收到以下错误错误:错误 TS2339:“UnaryFunction,可观察的>'。这是因为 generateArtistIdFromArtist(foo) 的返回实际上是一个字符串而不是一个 observable?我猜我应该让它返回一个 observable?
      • 是的,看起来是这样,generateArtistIdFromArtist 应该返回一个可以在 concat 响应中订阅的 observable。
      • @Ritesh,你应该在这里清楚地提到concat 是什么。它应该从 rxjs 导入。 import { concat } from 'rxjs/operators';
      • @AmitChigadani,他已经在使用一堆 rxjs 运算符。弄清楚这一点应该没什么大不了的。我们不是来喂勺子的。
      【解决方案3】:

      感谢@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!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-24
        • 2018-05-27
        • 2013-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多