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

I tried above code in console, it doesn't work as expected. It seems to me that although

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

will eventually trigger an error, what throws to the try is insteadly the animation's id. How do I catch such a "Maximum call stack size exceeded" error?

shenkwen
  • 3,536
  • 5
  • 45
  • 85
  • Those errors usually come from infinity loops right? – Binvention Feb 28 '16 at 16:54
  • What are you trying to achieve by using `requestAnimationFrame` ? – guest271314 Feb 28 '16 at 16:57
  • 1
    Also the thing about catching a maximum stack size exceeded error is I'm not sure how it would work. The only thing that the browser could do to allow the error to be caught is empty the stack then have the next function run be the catch function but at that point (and I don't think browsers can even get it that far) you would have no indication on where your code broke so anything you tried to run would be severely buggy at best. – Binvention Feb 28 '16 at 17:01
  • Thanks you this is the answer I am looking for. – shenkwen Feb 28 '16 at 17:03
  • Okay I'll put it in an answer – Binvention Feb 28 '16 at 17:06

4 Answers4

10

Maximum call stack size exceeded errors can be caught just like any other errors:

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

What to do in this situation (call stack size exceeded) is not defined in the ECMAScript specification, but in practice, all browsers do throw catchable exceptions. However, lacking a spec different browsers have chosen to throw different types of exceptions: I've seen Error, RangeError and InternalError.

The problem in your code is unrelated to that. The problem is that you're trying to catch exceptions that happen when you call requestAnimationFrame(). But your re() function doesn't run at that point, it runs during the next frame, as you requested. Inside of re(), you can wrap the recursive call to re() and catch the stack overflow exception there instead:

requestAnimationFrame(function re(){
  try {
    re();
  } catch (ex) {
    console.log("caught " + ex);
  }
});
Jeremy
  • 1
  • 85
  • 340
  • 366
4

the thing about catching a maximum stack size exceeded error is I'm not sure how it would work. The only thing that the browser could do to allow the error to be caught is empty the stack then have the next function run be the catch function but at that point (and I don't think browsers can even get it that far) you would have no indication on where your code broke so anything you tried to run would be severely buggy at best.

Another problem (which is probably why no browsers have this) is because most functions you would run after the error would simply try to restart normal web function in some way. Since you don't know what broke you can't stop it from happening again so you would end up crashing it again and again. Which would make both the users and the browsers mad at your web page.

So I guess the best that can be done is make sure your code doesn't have infinity loops and is able to run smoothly

a good description of stack size and how it works can be found in the answer to this question

Community
  • 1
  • 1
Binvention
  • 1,057
  • 1
  • 8
  • 24
  • 2
    **This is incorrect.** You are describing handling an out of memory error, which is different. [**It is entirely possible to catch these exceptions, they do not behave any differently than typical exceptions,** see my answer](https://stackoverflow.com/a/44733190/7952582). – Jeremy Jun 24 '17 at 05:38
3

You are calling the same function within the function re() inside your requestAnimationFrame() function. A correct way would be as follows:

function re(){
    //code here
    requestAnimationFrame(re); //loop back to start
}
Matthew Spence
  • 986
  • 2
  • 9
  • 27
  • 1
    Thank you. Although this is not the answer to my question, but it is the answer to a question I was about to ask. – shenkwen Feb 28 '16 at 17:04
  • 1
    I'd also like to point out that this is not an infinity loop where his code is an infinity loop. Using requestAnimationFrame in that way will cause the function to run until something causes it to stop but it's not technically an infinity loop because requestAnimationFrame is only called right before the browser is ready to redraw the Dom so you're not running a function continually like was in his question you're running a function periodically – Binvention Feb 28 '16 at 17:05
  • To clarify, I was only answering the second part of your question, I don't personally know how you could successfully catch a maximum call stack size error. Here's some information [on JavaScript Stack Sizes](http://bahmutov.calepin.co/javascript-stack-size.html), with some information on calculating their size. – Matthew Spence Feb 28 '16 at 17:14
1

This can be certainly done. More than that – if you'll stick to a meaningful pattern, you can determine how many times your function had run before the call stack overflowed (I wouldn't dare to try it on a function that is recursively invoked, rather than returned, as in the original question, because in this case the call stack can get really funky):

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()

Warning: This function starts an infinite loop, so it could crash you browser if you will try to run this in a distant future, when the common JS engines will be fully tail-call-optimized. For 10/2018, it gots to iteration no. 10454 in Chrome 69. In Firefox 62 the limit of stack overfow is changing (from 10077 to 20989, then 22160), probably due to some kind of smart runtime optimization. Haven't test it yet in Edge.

HynekS
  • 2,738
  • 1
  • 19
  • 34