【发布时间】:2021-10-11 15:38:36
【问题描述】:
我正在调用 spotify api,它返回一个像这样的对象:
{
next: 'https://api.spotify.com/v1/me/tracks?offset=100&limit=50'
items: [...]
}
其中 items 是刚刚进行的网络调用的结果,next 是用于获取下一个“页面”结果的 url。我想做的是在没有偏移的情况下进行初始调用,然后继续进行网络调用,直到下一个为空,这意味着用户没有更多的项目可以获取。如果没有更多项目,他们将返回 null 以供下一个。
这似乎是可能的,但似乎无法弄清楚如何正确地做到这一点。我正在寻找的是这样的:
readonly baseSpotifyUrl: string = 'https://api.spotify.com/v1';
constructor(private http: HttpClient) {}
public getTracks(url?: string): Observable<any> {
return this.http.get(url && url?.length > 0 ? url : `${this.baseSpotifyUrl}/me/tracks?limit=50`);
}
public getAllTracks(): Observable<any> {
const tracks$: Subject<any> = new Subject();
let next: string = '';
this.getTracks(next)
.subscribe({
next: (res: any): void => {
tracks$.next(res.items);
next = res.next;
// if res.next !== null, do this again now that we have set next to res.next
},
error: (err: any): void => {
console.error(err);
}
});
return tracks$;
}
这里的想法是我的组件将调用 getAllTracks() 并接收一个主题,然后新项目将不断地通过该主题推送,直到所有项目都被检索到。仅当有更多项目要获取时,前一个请求才返回时,我似乎无法弄清楚如何发出新的网络请求(res.next!== null)
编辑------------------------------ -------------
这完成了工作,但我觉得它很垃圾:
public getAllTracksSegment(itemsSubject: Subject<any>, nextSubject: Subject<string>, url?: string): void {
this.http.get(url && url?.length > 0 ? url : `${this.baseSpotifyUrl}/me/tracks?limit=50`).subscribe({
next: (res: any): void => {
itemsSubject.next(res.items);
nextSubject.next(res.next);
}
});
}
public getAllTracks(): Observable<any> {
const tracks$: Subject<any> = new Subject();
const next$: Subject<string> = new Subject();
next$.subscribe({
next: (next: any): void => {
if (next !== null) {
this.getAllTracksSegment(tracks$, next$, next);
}
}
});
next$.next('');
return tracks$;
}
【问题讨论】:
-
试过 takeWhile 操作符吗?
-
@AakashGarg http 请求 observables 在一次发射后关闭,所以 takeWhile 似乎没有为他们工作
-
@eko 我似乎越来越接近该问题的公认答案。我会尽快研究它,但似乎很有希望。似乎它没有返回第一组结果,但它正在进行正确数量的调用
标签: angular typescript asynchronous rxjs observable