具有承诺风格的顺序可观察量

时间:2017-07-11 17:15:00

标签: angular typescript rxjs angular2-observables

探索可观察对象,我遇到了一个问题,我需要在另一个函数完成后才执行函数。所有功能都是使用Http中的@angular/http服务的异步操作。

调用链应该是

  1. 检查是否存在播放列表。如果播放列表不存在,请创建它。
  2. GET推荐曲目
  3. 将推荐曲目添加到播放列表
  4. 通常情况下,我会用承诺书写这个,并且链条看起来像

    this.checkIfPlaylistExists()
        .then((exists) => {
            if(!exists) {
                return this.createPlaylist();
            }
        })
        .then(() => this.getRecommendedTracks(seedTracks)) //resolves tracks
        .then(this.addRecommendedTracksToPlaylist)
        .then(doSomethingElse)
        .catch();
    

    我的困惑是如何使用observable编写代码。到目前为止,我没有100%工作,看起来像这样

      createRecommendedTracksPlaylist(seedTracks: Track[]) {
        this.checkIfPlaylistExists()
          .map(exists => {
            if (!exists) {
              return this.createPlaylist();
            }
          })
          .map(() => this.getRecommendedTracks(seedTracks))
          .map((tracks) => this.addRecommendedTracksToPlaylist(tracks)) //<--- if I comment out this line, 'getRecommendedTracks' is executed and prints out response
          .mergeAll()
          .subscribe();
      }
    

    名为

    的函数
    getRecommendedTracks(seedTracks: Track[]) {
        seedTrackIds = seedTracks.map((track) => track.id).join(',');
        const recommendationsUrl = `https://api.spotify.com/v1/recommendations?seed_tracks=${seedTrackIds}`;
        return this.http.get(recommendationsUrl, options).map((res) => {
          const recommendedTracks = res.json().tracks as Array<Track>;
          console.log('Getting recommended tracks'); //Is only run if I don't run 'addRecommendedTracksToPlaylist' function
          console.log(recommendedTracks);
          return recommendedTracks;
        });
    }
    
    addRecommendedTracksToPlaylist(tracksToAdd) {
        console.log('Going to add tracks..');
        console.log(tracksToAdd); //Prints out 'Observable {_isScalar: false, ... }'
        const options = this.getAuthHeader();
        const playlistUri = '2OGx5l1ItjzMsQdQ0Hec6g';
        const addTracksUrl = `https://api.spotify.com/v1/users/${this.userId}/playlists/${playlistUri}/tracks`;
        return this.http.get(addTracksUrl, options);
    }
    

    修改:添加checkIfPlaylistExists代码(请注意,目前该播放列表始终存在)

      private checkIfPlaylistExists() {
        const options = this.getAuthHeader();
        const playlistUrl = `https://api.spotify.com/v1/users/${this.userId}/playlists`;
        return this.http.get(playlistUrl, options).map((res) => {
          const playlists = res.json().items as Array<any>;
          return playlists.some((e, i, a) => {
            return e.name.indexOf(this.playlistTitle) > -1;
          })
        });
      }
    

    总结一下

    • 如何使用observables编写这样的顺序执行顺序?
    • 如果我让函数getRecommendedTracks在&#39;链中运行,为什么功能addRecommendedTracksToPlaylist才会执行?
    • 我是否完全误解了Observable.map功能?我所看到的所有示例都将它用于单个对象和数组,但我不确定我是否正确使用它。

1 个答案:

答案 0 :(得分:2)

只需将您的.map()更改为.flatMap(),就可以了:

createRecommendedTracksPlaylist(seedTracks: Track[]) {
    this.checkIfPlaylistExists()
        .flatMap(exists => {
            if (!exists) {
                return this.createPlaylist();
            }
            return Observable.of(1);
        })
        .flatMap(() => this.getRecommendedTracks(seedTracks))
        .flatMap((tracks) => this.addRecommendedTracksToPlaylist(tracks))
        .subscribe();
}

如果playlist不存在,则需要返回一个虚拟Observable,因为flatMap期望返回Observable。 Observable.empty()因为刚结束流而无法工作。