Thursday, August 23, 2012

Undefined Timeout Burns

Doing some pleasurable (not overly) JavaScript development (slow...). I understand the advantages of dynamic languages (no I don't quite understand it, but I am being polite), but sometimes (most of the time) it burns.

var timeout_millis    = outer_params.timeout_millis;
var root_path         = outer_params.root_path;  
function loop_callback() {
  setTimeout(timeout_callback, timeout_millis);
  function timeout_callback() {
    var params = outer_params;
    do_something_and_then_call(params, loop_callback);
  }
}
loop_callback();
Simple enough, right? 

But this code failed miserably. 100% CPU. JS debugger locks up. JS console locks up. Good grief. 

Turns out I didn't set the 'timeout_millis' of 'outer_params'. So 'timeout_millis' will be undefined. And what does setTimeout() do? Does it think this a bit strange? No. It thinks zero is an excellent choice here. Thus your loop will really run wild, with the aforementioned effects. Making it hard to find your mistake, since there is no separation between the debugger and the debuggee code in Chrome, there's no separate debugger thread that one could protect from the debugged thread or process by prioritizing the debugger. The debugger simply locks up, partly because console gets too much ouput. 

Here's an immediate thing to help avoid the same situation in the future: 
if (!timeout_millis) {
  alert("timeout_millis == " + timeout_millis);
}
 And maybe

(function () {
  var original_setTimeout = window.setTimeout;
  window.setTimeout = function (callback, timeout_millis) {
    if (timeout_millis === undefined) {
      alert("timeout_millis == " + timeout_millis);
    }
    original_setTimeout(callback, timeout_millis);
  };
})();

Not well formatted, and untested, but you get the idea. 

No comments:

Post a Comment