I am making calls to the spotify api which returns an object like so:
{
next: 'https://api.spotify.com/v1/me/tracks?offset=100&limit=50'
items: [...]
}
where items are the result of the just-made network call and next is the url to use to get the next 'page' of results. What i would like to do is make an initial call with no offset, and then keep making network calls until next is null, meaning the user has no more items left to get. If there are no more items they send back null for next.
This seems possible but cant seem to figure out how to do it correctly. What I am looking for is something like this:
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$;
}
The idea here is that my component will call getAllTracks() and receive a subject and then new items will be continuously pushed through that subject until all the items have been retrieved. I cannot seem to figure out how to make a new network request when the previous one returns ONLY IF there are more items to get (res.next !== null)
EDIT-----------------------------------------------------------
This gets the job done but I feel that its trash:
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$;
}