如何捕获“超出最大调用堆栈大小”错误?

时间:2016-02-28 16:51:54

标签: javascript try-catch callstack

  try {
     requestAnimationFrame(function re(){
       re();
     })}
  catch (e){
       console.log(e);
     }

我在控制台上尝试了上面的代码,它没有按预期工作。在我看来,虽然

 requestAnimationFrame(function re(){
       re();
     })}

最终会触发错误,而try抛出的内容则是动画的id。如何捕获“超出最大调用堆栈大小”错误?

4 个答案:

答案 0 :(得分:6)

最大调用堆栈大小超出错误可以被捕获,就像任何其他错误一样:

try {
  function recur() { recur(); };
  recur();
} catch (ex) {
  console.log("caught " + ex);
}

在这种情况下做什么(超出调用堆栈大小)没有在ECMAScript规范中定义,但实际上,所有浏览器都会抛出可捕获的异常。但是,缺少规范不同的浏览器选择抛出不同类型的异常:我见过ErrorRangeErrorInternalError

您的代码中的问题与此无关。问题是您正在尝试捕获调用requestAnimationFrame()时发生的异常。但是你的re()函数不会在那一点上运行,它会在你请求的下一帧中运行。在re()内部,您可以将递归调用包装到re()并在那里捕获堆栈溢出异常:

requestAnimationFrame(function re(){
  try {
    re();
  } catch (ex) {
    console.log("caught " + ex);
  }
});

答案 1 :(得分:3)

您在re()函数内的函数requestAnimationFrame()内调用相同的函数。正确的方法如下:

function re(){
    //code here
    requestAnimationFrame(re); //loop back to start
}

答案 2 :(得分:2)

关于捕获最大堆栈大小超出错误的事情是我不确定它是如何工作的。浏览器唯一能够捕获错误的东西是空的堆栈,然后下一个函数运行是catch函数,但那时(我不认为浏览器甚至可以得到它)你没有迹象表明你的代码在哪里破了,所以你试图运行的任何东西都会出现严重错误。

另一个问题(这可能就是为什么没有浏览器有这个问题)是因为你在错误之后运行的大多数函数都会尝试以某种方式重启正常的web函数。既然你不知道什么打破了你可以阻止它再次发生,所以你最终会一次又一次地崩溃。这将使用户和浏览器都对您的网页感到愤怒。

所以我认为可以做的最好的事情就是确保你的代码没有无限循环并且能够顺利运行

可以在this question

的答案中找到有关堆栈大小及其工作原理的详细说明

答案 3 :(得分:0)

可以肯定。不仅如此-如果您坚持使用有意义的模式,则可以确定函数在调用堆栈溢出之前已运行了多少次(我不敢在递归调用的函数上尝试使用它,而不是原始问题中的 returned ,因为在这种情况下,调用栈可以变得非常时髦):

function doRecursionOrDieTryin(n = 0) {
    try {
    return doRecursionOrDieTryin(n + 1);
  } catch(err) {
    return `There was an exception: "${err}" when tryin' to make iteration no. ${n}`;
  }
}

doRecursionOrDieTryin()

警告:此功能会启动无限循环,因此如果您试图在很长的将来尝试运行此功能(当通用JS引擎将完全对尾调用进行优化)时,它可能会导致浏览器崩溃。对于10/2018,它需要迭代编号。在Chrome 69中为10454。在Firefox 62中,堆栈溢出的限制正在改变(从10077到20989,然后是22160),这可能是由于某种智能运行时优化所致。尚未在Edge中进行测试。