Skip to content

Commit 3e3faed

Browse files
authored
Merge pull request #23 from typelets/fix/home-page-load-performance
fix(mobile): home page load performance
2 parents e994a27 + 339a4ff commit 3e3faed

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

apps/mobile/v1/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/mobile/v1/src/services/api/folders.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,30 @@
33
* Handles all folder-related API operations
44
*/
55

6-
import { createHttpClient, AuthTokenGetter } from './client';
6+
import { AuthTokenGetter, createHttpClient } from './client';
77
import { Folder, FoldersResponse } from './types';
8-
import { fetchAllPages, createPaginationParams } from './utils/pagination';
8+
import { createPaginationParams, fetchAllPagesParallel } from './utils/pagination';
99
import { handleApiError } from './utils/errors';
1010

1111
export function createFoldersApi(getToken: AuthTokenGetter) {
1212
const { makeRequest } = createHttpClient(getToken);
1313

1414
return {
1515
/**
16-
* Get all folders with pagination
16+
* Get all folders with parallel pagination (optimized for performance)
17+
* Fetches pages in parallel instead of sequentially, eliminating delays
1718
*/
1819
async getFolders(): Promise<Folder[]> {
1920
try {
20-
const allFolders = await fetchAllPages<FoldersResponse, Folder>(
21+
return await fetchAllPagesParallel<FoldersResponse, Folder>(
2122
async (page) => {
2223
const params = createPaginationParams(page);
23-
return await makeRequest<FoldersResponse>(`/folders?${params.toString()}`);
24+
return await makeRequest<FoldersResponse>(
25+
`/folders?${params.toString()}`
26+
);
2427
},
2528
(response) => response.folders || []
2629
);
27-
28-
return allFolders;
2930
} catch (error) {
3031
return handleApiError(error, 'getFolders');
3132
}

apps/mobile/v1/src/services/api/utils/pagination.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,58 @@ function determineHasMorePages<T>(
8787
return pageItemsCount >= DEFAULT_PAGE_LIMIT;
8888
}
8989

90+
/**
91+
* Fetches all pages in parallel (after fetching page 1 to determine total)
92+
* Much faster than sequential pagination - eliminates artificial delays and waits
93+
* @param fetchPage - Function that fetches a single page of data
94+
* @param extractData - Function that extracts the data array from the response
95+
* @returns Array of all items across all pages
96+
*/
97+
export async function fetchAllPagesParallel<TResponse, TItem>(
98+
fetchPage: (page: number) => Promise<TResponse>,
99+
extractData: (response: TResponse) => TItem[]
100+
): Promise<TItem[]> {
101+
// Step 1: Fetch first page to get metadata
102+
const firstPageResponse = await fetchPage(1);
103+
const firstPageItems = extractData(firstPageResponse);
104+
105+
// Step 2: Determine how many total pages exist
106+
const resp = firstPageResponse as PaginationResponse<unknown>;
107+
let totalPages = 1;
108+
109+
if (resp.pagination) {
110+
totalPages = resp.pagination.totalPages ?? resp.pagination.pages ?? 1;
111+
} else if (resp.total !== undefined && resp.limit !== undefined) {
112+
totalPages = Math.ceil(resp.total / resp.limit);
113+
} else if (firstPageItems.length >= DEFAULT_PAGE_LIMIT) {
114+
// Got a full page, assume there might be more
115+
// But we can't know for sure, so we'll just return what we got
116+
return firstPageItems;
117+
}
118+
119+
// Step 3: If only one page, return immediately
120+
if (totalPages <= 1) {
121+
return firstPageItems;
122+
}
123+
124+
// Step 4: Create promises for ALL remaining pages (in parallel!)
125+
const remainingPagePromises: Promise<TItem[]>[] = [];
126+
for (let page = 2; page <= Math.min(totalPages, MAX_PAGES); page++) {
127+
remainingPagePromises.push(
128+
fetchPage(page).then(response => extractData(response))
129+
);
130+
}
131+
132+
// Step 5: Execute ALL requests in parallel
133+
const remainingPages = await Promise.all(remainingPagePromises);
134+
135+
// Step 6: Flatten and combine with first page
136+
return [
137+
...firstPageItems,
138+
...remainingPages.flat()
139+
];
140+
}
141+
90142
/**
91143
* Creates URL search params with pagination
92144
*/

0 commit comments

Comments
 (0)