I have a recursive function with an asynchronous interface that will probably exceed the depth limits of the stack when called:
function f(x, cb) {
if (x === 0) {
cb();
} else {
f(x - 1, cb);
}
}
f(1e6, function() {
console.log('done');
});
(and yes, it must be recursive, rewrite it as iterative, not viable).
I can solve this by making a recursive call asynchronously (e.g. via setTimeout
or window.postMessage
, which is supposedly faster):
function f(x, cb) {
if (x === 0) {
cb();
} else {
setTimeout(function() {
f(x - 1, cb);
}, 0);
}
}
f(1e6, function() {
console.log('done');
});
But it is much slower. Therefore, I want to make an asynchronous call only when it otherwise causes a stack overflow. Sort of
function f(x, cb) {
if (x === 0) {
cb();
} else {
if (getCurrentStackDepth() == getMaxStackDepth() - 42)
setTimeout(function() {
f(x - 1, cb);
}, 0);
} else {
f(x - 1, cb);
}
}
}
or, if this is not possible, at least detect when an overflow occurs and try again asynchronously. Something along the lines
function f(x, cb) {
if (x === 0) {
cb();
} else {
try {
f(x - 1, cb);
} catch (e) {
if (isStackOverflowError(e)) {
setTimeout(function() {
f(x - 1, cb);
}, 0);
} else {
throw e;
}
}
}
}
? Function.prototype.caller
, es5-es6. , .