Skip to content

Commit

Permalink
create useFetchBatched fook to fetch data with concurrent requests
Browse files Browse the repository at this point in the history
  • Loading branch information
mkholjuraev committed Jan 10, 2024
1 parent 47cd91c commit 6054ba2
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export { useInventory } from './useInventory';
export * from './CypressUtils';
export * from './useInsightsNavigate';
export * from './useExportPDF';
export * from './usePromiseQueue';
export * from './useFetchBatched';
1 change: 1 addition & 0 deletions packages/utils/src/useFetchBatched/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './useFetchBatched';
30 changes: 30 additions & 0 deletions packages/utils/src/useFetchBatched/useFetchBatched.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import usePromiseQueue from '../usePromiseQueue';

type FetchFunctionType = (filter: object | Array<string>, options?: object) => void;

//hook to enable fetching a lot of data from the API in concurrent API calls
const useFetchBatched = () => {
const { isResolving: isLoading, resolve } = usePromiseQueue();

return {
isLoading,
fetchBatched: (fetchFunction: FetchFunctionType, total: number, filter: object, batchSize = 50) => {
const pages = Math.ceil(total / batchSize) || 1;

const results = resolve([...new Array(pages)].map((_, pageIdx) => () => fetchFunction(filter, { page: pageIdx + 1, per_page: batchSize })));

return results;
},
fetchBatchedInline: (fetchFunction: FetchFunctionType, list: Array<string>, batchSize = 20) => {
const pages = Math.ceil(list.length / batchSize) || 1;

const results = resolve(
[...new Array(pages)].map((_, pageIdx) => () => fetchFunction(list.slice(batchSize * pageIdx, batchSize * (pageIdx + 1))))
);

return results;
},
};
};

export default useFetchBatched;
1 change: 1 addition & 0 deletions packages/utils/src/usePromiseQueue/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './usePromiseQueue';
46 changes: 46 additions & 0 deletions packages/utils/src/usePromiseQueue/usePromiseQueue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useCallback, useState } from 'react';
import pAll from 'p-all';

const DEFAULT_CONCURRENT_PROMISES = 2;

type PromiseQueueStateType = {
isResolving: boolean;
//undeterministic result type by p-all package
promiseResults: any;
};

// hook that provides queued promises with state
const usePromiseQueue = (concurrency = DEFAULT_CONCURRENT_PROMISES) => {
const defaultState: PromiseQueueStateType = {
isResolving: false,
promiseResults: undefined,
};
const [results, setResults] = useState(defaultState);

const resolve = useCallback(
async (fns: any) => {
setResults((state) => ({
...state,
isResolving: true,
}));
const results: any = await pAll(fns, {
concurrency,
});
setResults({
isResolving: false,
promiseResults: results,
});

return results;
},
[concurrency]
);

return {
isResolving: results.isResolving,
results: results.promiseResults,
resolve,
};
};

export default usePromiseQueue;

0 comments on commit 6054ba2

Please sign in to comment.