如何遍历HTTP请求循环并将每次迭代的数据适当地存储到数组中

时间:2017-04-11 23:49:21

标签: javascript typescript asynchronous xmlhttprequest angular-promise

我正在使用Spotify的API搜索功能来迭代定义为:

的SongSearchParams数组
export class SongSearchParams {
    public title: string;
    public artist: string;

    constructor(title: string, artist: string){
        this.title = title;
        this.artist = artist;
    }
}

我的HTTP请求如下:

  searchTrack(searchParams: SongSearchParams, type='track'){
    var headers = new Headers({'Authorization': 'Bearer ' + this.hash_params.access_token});
    this.user_url = "https://api.spotify.com/v1/search?query="+searchParams.artist+' '+
                    searchParams.title+"&offset=0&limit=1&type="+type+"&market=US";

    return this.http.get(this.user_url, {headers : headers})
      .map(res => res.json());
  }

在我的一个组件打字稿文件中,我可以访问SongSearchParams数组,我想在单击某个按钮时单独传入此searchTrack函数并保存相册图像,轨道名称和艺术家一首歌。

onClick(){
  for(let searchQuery of this.songService.songSearches){ 
    this.spotifyserv.searchTrack(searchQuery)
      .subscribe(res => {
        this.searchedSong.artist = res.tracks.items[0].artists[0].name;
        this.searchedSong.title = res.tracks.items[0].name;
        this.searchedSong.imagePath = res.tracks.items[0].album.images[0].url;
        console.log(this.searchedSong);
        this.songService.addSong(this.searchedSong);
      })
  }
}

当我运行此代码时,控制台会为每次迭代记录正确的歌曲,但由于某种原因,我的songSearches数组中的最后一首歌曲会在songSearches时间内实际添加。

谷歌搜索这个问题的答案,似乎我需要使用then()功能正确使用Promise,所以我尝试实现(对于searchTrack函数):

这让我认为这是我的addSong函数的问题

addSong(song: Song){
    this.songs.push(song);
    this.songsChanged.next(this.songs.slice());
}

虽然我真的不知道它有什么问题,所以我的第二个预感是我应该使用一个接一个地叫出来的承诺(我已经尝试过)但是没有实现。

2 个答案:

答案 0 :(得分:0)

我想看看forkjoin

这样的话:

let obsArray = [];

for(let searchQuery of this.songService.songSearches) {
    obsArray.push(this.spotifyserv.searchTrack(searchQuery));
}

Observable.forkJoin(obsArray)
    .subscribe(results => {
        // results[0]
        // results[1]
        // ...
        // results(n)
    });

答案 1 :(得分:0)

我发现了我的问题的解决方案,虽然我不知道它为什么修复它(我只有一个假设)。

在我创建onClick()方法的类中,我有一个名为songSearched的类型为Song的私有成员,我试图覆盖每个添加到列表中的歌曲。我反而将该函数改写为:

onClick(){
  for(let searchQuery of this.songService.songSearches){ 
    this.spotifyserv.searchTrack(searchQuery, 
          response => {
            let res = response.json();
            console.log(res.tracks.items[0].album.images[0].url);
            console.log(res.tracks.items[0].name);
            console.log(res.tracks.items[0].artists[0].name);
            let searched_song = {artist : null, title : null, imagePath : null}
            searched_song.artist = res.tracks.items[0].artists[0].name;
            searched_song.title = res.tracks.items[0].name;
            searched_song.imagePath = res.tracks.items[0].album.images[0].url;
            console.log(searched_song);
            //song_queue.push(searched_song);
            this.songService.addSong(searched_song);
          }
    )
  }
}

在这里,我改为创建一个新的search_song,将其附加到函数本身的列表中,对于每个请求,存在一个search_Song。我想在发生之前我正在覆盖相同的搜索歌曲,当它到达addSong(searchingSong)时,最终的歌曲已经用Spotify的API进行了搜索,并且已经覆盖了之前的搜索,因此歌曲不断增加。

虽然这仍然无法解释为什么控制台日志在我原来的尝试中在前一行中有效。