我试图将两个异步调用链接到Spotify API - 一个获取播放列表的名称,另一个创建一个播放列表,如果它不存在于检索的播放列表列表中。目前,我确定播放列表是否已存在的代码如下所示:
containsPlaylist(playlistToCreate: string): Observable<any> {
this.spotifyService.getUserPlaylists().flatMap(data => data.items).map((item: Track) => item.name).subscribe(name => {
console.log(name);
if (name === playlistToCreate) {
console.log('returning true');
return Observable.of(true);
}
});
console.log('returning false');
return Observable.of(false);
}
但是,这显然是有缺陷的,因为异步调用getUserPlaylists()不必在到达“Observable.of(false)”语句之前返回。因此,即使调用最终返回,containsPlaylist也已返回false(据我所知)。我相信情况就是如此,因为控制台将按以下顺序打印console.log语句:
'return false','播放列表存在:false','创建播放列表','返回true'
下面是调用containsPlaylist的地方,它只检查函数是返回true还是false。
this.containsPlaylist(this.playlistToCreate).subscribe(playlistExists => {
console.log('playlist exists: ' + playlistExists);
if (!playlistExists) {
console.log('creating playlist')
this.spotifyService.createPlaylist(this.playlistToCreate, this.spotifyUser.id).subscribe(data => data);
}
});
所以我的问题是:
如何让Observable.of(false)语句返回我的订阅内部,如Observable.of(true)语句?
或者,如果这是错误的思考方式,我如何修改containsPlaylist以正确返回getUserPlaylists返回的现有播放列表中是否包含playlistToCreate。谢谢!
你做得比实际困难得多。一般来说,当你有一个可观察的,但想要另一个,你不应该订阅。相反,您应该使用运算符:
containsPlaylist(playlistToCreate: string): Observable<boolean> {
return this.spotifyService.getUserPlaylists().
.map(arrayOfTracks => arrayOfTracks.some(track => track.name === playlistToCreate));
}
然后,如果第一个observable发出false,则可以使用switchMap而不是在订阅回调内部进行订阅:
this.containsPlaylist(this.playlistToCreate)
.filter(result => !result)
.switchMap(() => this.spotifyService.createPlaylist(this.playlistToCreate, this.spotifyUser.id))
.subscribe(() => {});