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

调用链应该是

  • 检查播放列表是否存在。如果播放列表不存在,请创建它。
  • GET 推荐轨道
  • 将推荐轨道添加到播放列表

  • 通常,我会用 Promise 来写这个,并且有一个看起来像这样的链
    this.checkIfPlaylistExists()
        .then((exists) => {
            if(!exists) {
                return this.createPlaylist();
            }
        })
        .then(() => this.getRecommendedTracks(seedTracks)) //resolves tracks
        .then(this.addRecommendedTracksToPlaylist)
        .then(doSomethingElse)
        .catch();
    

    我的困惑是我将如何使用 observables 来编写代码。到目前为止我没有 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 在“链”中运行时才执行 addRecommendedTracksToPlaylist 函数?
  • 我完全误解了 Observable.map 函数吗?我看过的所有示例都将它用于单个对象和数组,但我不确定我是否正确使用它。
  • 最佳答案

    只需将您的 .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() 不起作用,因为它只是结束了流。

    关于angular - 类似 promise 风格的顺序 observables,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45040851/

    10-13 01:43