【发布时间】:2016-04-29 14:13:22
【问题描述】:
我正在编写一项服务,人们可以在其中粘贴来自 Spotify 播放列表的网址,然后将播放列表导出到不同的服务中。对于粘贴在请求中的每个曲目 url,需要向 Spotify api 发出请求。
这段代码:
Rx.Observable.fromArray<ITrackIdentifier>( this._allTracks )
.pluck<string>( "id" )
.distinct()
.flatMap(
( trackId ) => this.spotifyService.lookupTrack( trackId ).
catch( ( error ) => this.handleError( error ) ))
.subscribe(
( result ) => this.handleTrackLookupResult( result ),
( error ) => this.handleError( error ),
() => this.handleComplete()
);
- 从 ITrackIdentifiers 列表创建一个 observable
- 采用轨道标识符的 id 来创建一个可观察的字符串 (id)
- 删除列表中的所有重复 ID
- 为每个对 spotify 进行的 http 调用创建一个 observable(并捕获错误)
- 使用平面图将所有这些可观察对象的结果合并到一个流中
这实际上工作正常,除非添加大量曲目。我的一个示例播放列表有超过 500 首曲目,因此立即进行了 500 次调用,浏览器需要处理它们/从缓存中返回项目,因此浏览器运行缓慢并锁定,并且当我超过 api 调用限制时,spotify 返回大量错误.
我希望只能同时运行 10 个呼叫。 Merge with maxConcurrent set 似乎是Stackoverflow 上讨论的完美解决方案。
看起来像这样:
Rx.Observable.fromArray<ITrackIdentifier>( this._allTracks )
.pluck<string>( "id" )
.distinct()
.map(
( trackId ) => this.spotifyService.lookupTrack( trackId ).
catch( ( error ) => this.handleError( error ) ))
.merge(10)
.subscribe(
( result ) => this.handleTrackLookupResult( result ),
( error ) => this.handleError( error ),
() => this.handleComplete()
);
但它只是不起作用。在 chrome 网络调试器中,您可以看到同时进行的所有调用,并且大多数调用会排队很长时间,直到它们失败。
为什么这不起作用?我还能如何解决这个问题?
这是现阶段项目的Github checkin:
【问题讨论】:
-
Merge 可以正常工作。它限制了订阅的数量。但是在“合并”之前,您有一个“地图”,它实际上会发出所有请求,然后才开始“合并”。
标签: javascript typescript rxjs