Javascript Bug: Processing takes progressively longer

Javascript Bug: Processing takes progressively longer each time you click a button or hit enter.

You might guess this is a Memory Leak Problem, and since this is Javascript you might suggest it could be the much hyped circular reference problem that can occur between a JavaScript object and a DOM object. Close but no cigar.

I've only seen this symptom 3 times in the wild, but every time the actual culprit has been a problem with event handlers, i.e. the same event handlers are being re-added without the old ones being destroyed. In the worst case each run of an event handler added another which generated an exponential explosion of handlers.

Depending on how you think about this you might want to classify it as a memory leak, but a progressive consumption of memory is not what's causing the slow down. Instead it's just huge stack of handlers being queued up and taking forever to run.

For a quick fix you can wrap this if statement around your add handler statement:

if(!this.HandlerAdded)
{
/*$addHandler code here*/

this.HandlerAdded = true;
}

This if block will only allow the handler to be added once. Note that HandlerAdded is a property of the function and not a variable. This means it won't error out as undefined even though it doesn't exist yet; it also means that it will persist to subsequent calls.

Alternately you could do something like this:

function EnableKeyPressHandler(enabled)
{

if(enabled== true)
{
 if(!this.HandlerAdded)
 {
      $addHandler(myObject, "keypress", CheckKey);
      this.HandlerAdded = true;
 }
}
else if(enabled!= true)
{
  if(this.HandlerAdded)
  {
      $removeHandler(myObject, "keypress", CheckKey);
      this.HandlerAdded = false;
  }
}

}

Then you can replace the appropriate add/remove handler calls with a call this method (note: this code is a mod/simplification of working code, but has not itself been tested).

Ideally you would do further refactoring to make sure that calls to add/remove handlers are made at appropriate times.

0 comments: