Last active
April 29, 2023 13:22
-
-
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?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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