基于 Angular 5 observable.subscribe() 中的单个值有条件地返回,用于将异步调用链接在一起
Conditionally returning based on a single value inside Angular 5 observable.subscribe() for chaining asynchronous calls together
我正在尝试将对 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() 不必 return 到达 "Observable.of(false)" 语句之前。因此,即使最终调用 returns,containsPlaylist 也已经 returned false(据我所知)。我相信情况确实如此,因为控制台将按以下顺序打印 console.log 语句:
'returning false'、'playlist exists: false'、'creating playlist'、'returning true'
下面是调用 containsPlaylist 的地方,它只是检查函数 return 是真还是假。
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) 语句一样发送到 return?
或者如果这是错误的思考方式,我如何修改 containsPlaylist 以正确 return 无论 playlistToCreate 是否包含在由 getUserPlaylists return 编辑的现有播放列表中。
谢谢!
你让它变得比必要的更难。通常,当您有一个可观察对象但想要另一个可观察对象时,您不应该订阅。相反,您应该使用运算符:
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(() => {});
我正在尝试将对 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() 不必 return 到达 "Observable.of(false)" 语句之前。因此,即使最终调用 returns,containsPlaylist 也已经 returned false(据我所知)。我相信情况确实如此,因为控制台将按以下顺序打印 console.log 语句:
'returning false'、'playlist exists: false'、'creating playlist'、'returning true'
下面是调用 containsPlaylist 的地方,它只是检查函数 return 是真还是假。
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) 语句一样发送到 return?
或者如果这是错误的思考方式,我如何修改 containsPlaylist 以正确 return 无论 playlistToCreate 是否包含在由 getUserPlaylists return 编辑的现有播放列表中。 谢谢!
你让它变得比必要的更难。通常,当您有一个可观察对象但想要另一个可观察对象时,您不应该订阅。相反,您应该使用运算符:
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(() => {});