One of the problems I commonly have to deal with is asynchronous pagination. Sometimes a service only returns me a page of results at a time, but the rest of my application Doesn’t Care™. All I want are the results.

Imagine you have a function that returns a Promise:

function getPage(page) {
  return fetch(endpoint, { page });
}

What you can do is attach a collector function that will either return another Promise or return the collected results. The mechanism of Promises allows that if another Promise is returned, it will wait and assume the resolution of the returned Promise.

getPage(1)
.then(function collect(result) {
	if (!result.hasNext) return result;

	return getPage(result.page + 1)
	.then(collect)
	.then(inner => extend(result, inner));
});

Ta-da! The outermost Promise will be a Promise for the collected results of all pages.