-
-
Notifications
You must be signed in to change notification settings - Fork 54
Description
I'm planning to change the interface of API that returns a collection of entities to a more intuitive one in the next major release.
Currently, we have three methods to fetch a collection of entities; fetchMany
, fetchAll
and iterate
. The difference between fetchMany
and iterate
is the return type. fetchMany
just returns an array while iterate
returns an async iterable. fetchAll
is for APIs that don't support pagination, such as suggestions, announcements, etc.
// This is an array. You can check if there's more by `done`
const { value: collection1, done } = await masto.timelines.fetchHome();
// This is an asyncIterable. You can fetch more by calling .next()
const collection2 = masto.timelines.iterateHome();
// This is an array without pagination
const collection3 = await masto.announcements.fetchAll();
However, this implementation has some disadvantages. It is simply intricate because we have to maintain at least two methods for each API. On top of that, there had been APIs that used to not support pagination but added a Link
header later on. If we mapped such API by fetchAll()
at first and then they come to support pagination, we have to make a breaking change to rename fetchAll()
to fetchMany()
and also introduce iterate()
.
To solve this, I'm planning to integrate these three methods into a single method named list
, and implement PromiseLike<T>
to the Pagination
class. It would look like this; since Paginator
is now then-able, we can await
to get the first page, while you can also iterate over multiple pages by using the iteration protocol.
// You can directly fetch an array
const array = await masto.announcements.list();
// While you can also iterate over the collection
for await (const items of masto.announcements.list()) {
console.info(items);
}
I'm planning to prevail this change to all methods that currently return an array. As a result, we can achieve two features ―fetching a single page, and iterating over multiple pages―in a single method. Furthermore, even if Mastodon started to support pagination in some API, we can smoothly start to adopt the update without any breaking changes.
This is inspired by twitter-api-typescript-sdk returns AsyncIterable + PromiseLike
for APIs that supports pagination
https://github.com/twitterdev/twitter-api-typescript-sdk/blob/0d12a20a76d6dd9c346decf9cc80bc611975d43f/src/types.ts#L21
The possible drawbacks are the fact that PromiseLike
is not an actual Promise
, so it's a bit inconvenient when you need an actual Promise
object. However, PromiseLike
can be easily converted into Promise
by calling then
, so I think this is not a critical problem.
const result1 = masto.announcements.list() instanceof Promise;
const result2 = masto.announcements.list().then() instanceof Promise;
// result1 === false, result2 === true