Created
March 15, 2018 05:42
-
-
Save IZEDx/8bafc86ca9f45295559c73817019d2fa to your computer and use it in GitHub Desktop.
Demonstration of using setImmediate() and async/await-syntax to program recursively without exceeding the maximum call stack size and tail call optimizations
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
/** | |
* Adds the passed function to the JavaScript Message Queue to be executed by the Event Loop, | |
* wraps a Promise around that and resolves any asynchronous values. | |
* This allows to call a function asynchronously and on the Event Loop, which doesn't grow the call stack, | |
* but can be used in a synchronous manner using await. | |
* @param fn The function to be executed, can be async. | |
* @param args The arguments to be passed to this function. | |
*/ | |
function immediate<T, K>(fn: (...args: K[]) => T|Promise<T>, ...args: K[]) { | |
return new Promise<T>(res => { | |
setImmediate(() => { | |
const t = fn(...args); | |
if (t instanceof Promise) { | |
t.then(res); | |
} else { | |
res(t); | |
} | |
}); | |
}); | |
} | |
/** | |
* Recursive implementation of the Fibonacci Sequence. | |
* Makes the callstack grow. | |
* @param n Iterations to calculate. | |
* @returns {[number, number]} Tuple containing the result of n and n-1 iterations. | |
*/ | |
function fibRecusive(n: number): [number, number] { | |
if (n <= 1) return [1, 1]; | |
const [n1, n2] = fibRecusive(n - 1); // Stack trace is a bitch | |
return [n1 + n2, n1]; | |
} | |
/** | |
* Asynchronous recursive implementation of the Fibonacci Sequence, using immediate wrapper. | |
* Works recursive but does not add to the callstack. | |
* @param n Iterations to calculate. | |
* @returns {[number, number]} Tuple containing the result of n and n-1 iterations. | |
*/ | |
async function fibImmediate(n: number): Promise<[number, number]> { | |
if (n <= 1) return [1, 1]; | |
const [n1, n2] = await immediate(fibImmediate, n - 1); // Async for the rescue | |
return [n1 + n2, n1]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment