We have an API that will respond with a boolean hasMore and a token. If hasMore is true, we can do another API call using that token to get the next set of results. This process needs to be repeated until hasMore is false. Then, the whole resulting list needs to be emitted as one single list and the observable needs to be completed.
I've managed to implement this using a BehaviorSubject:
function getAll() {
const subject = new BehaviorSubject(undefined);
const obs = subject
.asObservable()
.pipe(
flatMap(token => getRes(token)
.pipe(
tap(result => result.hasMore ? subject.next(result.token) : subject.complete())
)
),
map(result => result.items),
reduce((acc, items) => acc.concat(items), [])
);
return obs;
}
(where getRes() returns an observable that does an API call with the provided token and emits the API response body as JSON)
See https://rxviz.com/v/7J245RDo
However, I was wondering if there was a pure observable way of doing this, without using a BehaviorSubject. I tried playing around with repeatWhen, but couldn't figure out how to change the input data, and yet map to the response data.