I recently needed a blazing fast concurrent to fetch items from an API. Of course, I could use a combination of async-awaits and some cryptic code with promises and so I took a stab at doing this in rxjs.
import { Observable } from 'rxjs';
export function doPaginate<T>(
fetchPage: (page: number) => Promise<{ totalRows: number; resultItems: T[] }>,
): Observable<T> {
return new Observable<T>((subscriber) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
try {
const firstPage = await fetchPage(1);
const totalPages = Math.ceil(
firstPage.totalRows / firstPage.resultItems.length,
);
firstPage.resultItems.forEach((item) => subscriber.next(item));
for (let pageNum = 2; pageNum <= totalPages; pageNum++) {
const { resultItems } = await fetchPage(pageNum);
resultItems.forEach((item) => subscriber.next(item));
}
subscriber.complete();
} catch (error) {
subscriber.error(error);
}
})(); // Immediately invoked async function expression
});
}