Pagination
Pagination
MailSlurp API endpoints use pagination to return lists of entities. Pagination is the process of splitting a large list of entities into smaller pages. This allows you to retrieve entities in batches and is useful for performance and usability. This post will demonstrate how to iterate over paginated results and fetch all entities.
Key points
- MailSlurp endpoints return paginated results
- Page index is zero based (0 = first page)
- Some endpoints return negative totals (this means the total is too large to count quickly)
- You accumulate all entities by looping over pages until
page.emptyorpage.lastis true
The email and inbox endpoints have a fixed page size of 20 items per page. This is to allow for caching performance.
Counting entities
To get the total number of emails for an inbox you can do the following:
// if you need the countconst count = await inboxController.getInboxEmailCount({ inboxId: inbox.id});expect(count.totalElements).toBeGreaterThan(0);These methods are also available for other endpoints and provide an accurate entity count.
Do not rely on the pagination result for counting entities. The pagination result may not be accurate if the entity count is large. Use the count methods instead.
Basics
When you are fetching a list of emails or inboxes you will receive a paginated response. The response will contain a list of entities and some pagination metadata.
const page = await emailController.getEmailsOffsetPaginated({ inboxId: [inbox.id], page: undefined, // 0 based page index here size: undefined // page size here});// properties of a pageconst { content, // the emails in this page numberOfElements, // the number of elements in the result empty, // is the page empty? last, // is the page the last one? pageable // the pagination object for paging through results} = page;// properties of the returned paginationconst { pageSize, // the page size pageNumber // the 0 based page number} = page.pageable ?? {};Negative totals
For some endpoints the total may be negative. This is because the total is too large to quickly count. In this case you can use the count methods to get an accurate count.
const pagination = await emailController.getEmailsOffsetPaginated({ inboxId: [inbox.id]});// the total is -1, indicating that the total count is not availableexpect(pagination.totalElements).toEqual(-1);expect(pagination.totalPages).toEqual(-1);Fetching all entities
To paginate through all entities use the following technique:
// fetch emails using offset paginationlet finished = false;let emails = [];let pageIndex = 0;const pageSize = 10;do { // fetch next page const page = await emailController.getEmailsOffsetPaginated({ page: pageIndex, size: pageSize, inboxId: [inbox.id] }); // add to list of emails emails.push(...(page.content ?? [])); // increment page index pageIndex++; // add a sleep to the loop to prevent rate limiting await sleep(100); // mark loop finished if page is empty or on last page if (page.empty || page.last) { finished = true; }} while (!finished);Use a timeout or sleep in any loop method to avoid rate-limiting
How stepping works
In this demonstrate we can step through pages using a custom page size:
// given an inbox with 7 emailsconst count = await inboxController.getInboxEmailCount({ inboxId: inbox.id});expect(count.totalElements).toEqual(7);
// paginate to demonstrate pagingconst page1 = await emailController.getEmailsOffsetPaginated({ page: 0, // 0-based index, 0 means first page size: 3, inboxId: [inbox.id]});
// content and number of elements matching the page sizeexpect(page1.numberOfElements).toEqual(3);expect(page1.content?.length).toEqual(3);// is not last or emptyexpect(page1.last).toEqual(false);expect(page1.empty).toEqual(false);
// can page again to page 2const page2 = await emailController.getEmailsOffsetPaginated({ page: 1, size: 3, inboxId: [inbox.id]});// expect 3 inboxes againexpect(page2.numberOfElements).toEqual(3);expect(page2.content?.length).toEqual(3);// is not last or empty againexpect(page2.last).toEqual(false);expect(page2.empty).toEqual(false);
// now get the last pageconst page3 = await emailController.getEmailsOffsetPaginated({ page: 2, size: 3, inboxId: [inbox.id]});// expect final inbox (7 - 3 - 3 = 1)expect(page3.numberOfElements).toEqual(1);expect(page3.content?.length).toEqual(1);// is the last page (and not empty)expect(page3.last).toEqual(true);expect(page3.empty).toEqual(false);