探索 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;
})
});
}
所以总结一下
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/