Skip to content

Instantly share code, notes, and snippets.

@ryanjduffy
Created December 21, 2020 18:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanjduffy/31fb8fcd2cfd7bf3740567b1111f0fba to your computer and use it in GitHub Desktop.
Save ryanjduffy/31fb8fcd2cfd7bf3740567b1111f0fba to your computer and use it in GitHub Desktop.
useIdleMapReduce
function useIdleMapReduce<T = any, M = T, R = M>(
array: T[],
map: (item: T, index: number, array: T[]) => M,
reduce: (acc: R, value: M, index: number, array: M[]) => R,
initialValue: R
) {
const ref = useRef({ array, out: [] as M[], acc: initialValue, index: 0, id: null });
const result = useCallback(() => {
if (ref.current.index !== -1) callback(true);
return ref.current.acc;
}, [ref, array]);
const schedule = (fn: () => void) => {
ref.current.id = window.requestIdleCallback(() => fn());
};
const callback = (finish?: boolean) => {
const now = Date.now();
const { array: a, out } = ref.current;
while (ref.current.index < a.length) {
out[ref.current.index] = map(a[ref.current.index], ref.current.index, a);
ref.current.acc = reduce(ref.current.acc, out[ref.current.index], ref.current.index, out);
ref.current.index = ref.current.index + 1;
if (!finish && Date.now() - now > 62 && ref.current.index < a.length) {
schedule(callback);
return;
}
}
ref.current.index = -1;
ref.current.id = null;
};
useMemo(() => {
if (ref.current.array !== array) {
if (ref.current.id) window.cancelIdleCallback(ref.current.id);
ref.current.array = array;
ref.current.out = [];
ref.current.index = 0;
ref.current.id = null;
ref.current.acc = initialValue;
}
if (Array.isArray(array) && !ref.current.id) {
schedule(callback);
}
}, [array]);
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment