try/catch-有多少递归调用?调用堆栈大小循环



我有一个函数,我想在不停止脚本的情况下循环它。但当我使用"console.log"时,该功能就会停止。如果我删除它,函数将继续。

如何使这个函数在超过堆栈大小后继续?

var i = 0;
function computeMaxCallStackSize() {
try {
i++;
console.log(i);
//some function to execute
computeMaxCallStackSize();
} catch (e) {
//'e' is the error when max stack exceeds
// setTimeout() is to wait before calling the function
// if stack size exceeds it recalls the function
setTimeout(computeMaxCallStackSize(), 0);
}
}
computeMaxCallStackSize();

编辑:此函数将导致堆栈溢出并继续。

var a = 1;
var b = 8769; //stack size
func(a);
function func(a) {
try {
console.log(a);
if(a % b === 0){
setTimeout( function() {func(a+1); }, 0);
} else {
func(a+1);
}

} catch (e) {
console.error(e);
setTimeout( function() {func(a); }, 1);
}
}

如果我删除它,函数将继续。

不,它不会,它也会完成,但要晚得多。console.log()占用了更多的资源,因为它需要在控制台中呈现文本,所以它更快地到达调用堆栈。

你刚刚做了一个无限循环,它将一直运行到浏览器内存耗尽。

我看不到在nodejs中捕获stackoverflow的方法。根据我从其他生态系统了解到的情况,这是不可能的。例如,请参阅C#捕获堆栈溢出异常。另请参阅有关异常的说明:

有些异常在JavaScript层是不可恢复的。这样的异常总是会导致Node.js进程崩溃。示例在C++层中包括assert((检查或abort((调用。

进程堆栈是固定大小的连续内存块,通常不是很大(因为它的目的是利用进程缓存(。这意味着你不能";延伸";根据您的意愿(仅在流程开始时(。如果你不能扩展它,为什么每次调用函数都要检查它的边界呢?操作系统会帮你完成任务并破坏你的进程!

我知道,在高度递归的学术算法的情况下,这并不总是可能的,但从业务角度来看,你应该始终打开递归,尤其是在递归很深的情况下。即使你认为你控制了它(比如,它只有2000深,谁在乎呢?(,但事实上你没有,因为通常你不能完全控制调用方堆栈大小和最终用户平台的限制。

但是

如果你真的想在stackoverflow之后恢复你的进程,并且你已经准备好进行这样的冒险(win-api、从源代码构建节点等(,我会把这个留给你。

您的setTimeout有点毫无意义:

// Current code:
setTimeout(computeMaxCallStackSize(), 0);
// What you really want:
setTimeout(computeMaxCallStackSize, 0);

为了回答你的问题——你不想写超过堆栈的代码——这总是表明代码写得不好。此外,实际上没有一种方法来检查堆栈大小或检查堆栈何时为"0";清除";再次(有充分的理由——人们会滥用这些知识来编写糟糕的代码(。

如果你需要递归,你几乎总是在一个";"深度";参数,以便函数在某个调用深度后停止。类似这样的东西:

function someRecursiveFunction(_depth = 0) {
if(_depth < 100) {
// do the stuff
someRecursiveFunction(_depth + 1)
}
throw new Error('Oh no, we called this function too many times');
}

如果你这样做只是为了搞笑,并且真的想看看堆栈洞有多深,我想你可以计算迭代次数。正如其他评论中所提到的,控制台日志将占用额外的资源,因此您可能会在没有日志记录的情况下获得100万次迭代,而在有日志记录的条件下仅获得10万次迭代。同样,没有办法询问JS运行时";我还剩多少资源";。您正在编写的函数只是一个";为了好玩";实验,不应在实际代码中使用。

最新更新