Skip to content

Instantly share code, notes, and snippets.

@ziomarco
Last active April 29, 2023 13:22
Show Gist options
  • Save ziomarco/5b95566c9e79b724d5968e59b9323fa1 to your computer and use it in GitHub Desktop.
Save ziomarco/5b95566c9e79b724d5968e59b9323fa1 to your computer and use it in GitHub Desktop.
Need to iterate on functions when potentially multiple valid arguments without risking a RangeError exception?
/**
Do you need to handle a potential RangeError (Max call stack size exceeded) because of a recursive function?
Maybe the input should change in several ranges basing on random criterias?
Please don't try/catch things lot of times, use this :)
Example Usage:
[ this is my recursive function ] [these are my fn args], [this are values that will be tried instead of 'ITERATE' arg ]
const simplifiedTrack: FeatureCollection = handleSyncRecursion(simplifyGeoJsonWithMaxPointsLimit, [track, 50, 'ITERATE'], [0.001, 0.005, 0.008, 0.01]);
*/
/**
*
* @param fn<T> Function to iterate on
* @param fnargs Args to pass to fn (include a 'ITERATE' in your list to indicate whether param you want to iterate on)
* @param valuesToIterate Value to substitute to 'ITERATE'
* @returns T
*/
export function handleSyncRecursion<T>(fn: Function, fnargs: any[], valuesToIterate: any[]): T {
let retval: T;
const args = fnargs;
const argToIterateIdx = fnargs.findIndex(arg => arg === 'ITERATE');
if (!argToIterateIdx) {
throw new Error('Missing "ITERATE" argument to call the function');
}
for (const currIteratorVal of valuesToIterate) {
try {
console.debug(`Iterating ${fn.name} with value ${currIteratorVal} on args[${argToIterateIdx}]`);
args[argToIterateIdx] = currIteratorVal;
retval = fn(...args);
break;
} catch (e) {
if (e instanceof RangeError) {
continue;
}
throw e;
}
}
return retval;
}
/**
*
* @param fn<T> Function to iterate on
* @param fnargs Args to pass to fn (include a 'ITERATE' in your list to indicate whether param you want to iterate on)
* @param valuesToIterate Value to substitute to 'ITERATE'
* @returns T
*/
export async function handleAsyncRecursion<T>(fn: Function, fnargs: any[], valuesToIterate: any[]): Promise<T> {
let retval: T;
const args = fnargs;
const argToIterateIdx = fnargs.findIndex(arg => arg === 'ITERATE');
if (!argToIterateIdx) {
throw new Error('Missing "ITERATE" argument to call the function');
}
for (const currIteratorVal of valuesToIterate) {
try {
console.debug(`Iterating ${fn.name} with value ${currIteratorVal} on args[${argToIterateIdx}]`);
args[argToIterateIdx] = currIteratorVal;
retval = await fn(...args);
break;
} catch (e) {
if (e instanceof RangeError) {
continue;
}
throw e;
}
}
return retval;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment