DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Jason has posted 22 posts at DZone. View Full User Profile

JavaScript: Wrap All Methods (functions) In A Class With An Error Handler.

12.18.2009
| 3825 views |
  • submit to reddit
        Example of a way to wrap all methods in a class with an error handler. Could stand more improvement.

/**
@Description: Takes in an exception or string and turns it into an Error object,
  then appends the caller name to the message.
@Returns: A new Error object or null.
*/
function wrapError (e, caller)
{
  if (null === e) { return null; }
  var ret = ( (typeof e) === (typeof "") ) ? new Error(e) : new Error(e.message);
  ret.stackTrace = e.stackTrace || [];
  ret.stackTrace.push(caller);
  return ret;
}

/**
@Description: Returns a method (function) wrapped in an error handler. Does not 
  affect the behavior of the underlying function. Does not affec the function 
  either, only returns the wrapped function, doesn't modify it directly.
  Usage: function foo() { throw new Error("bar"); }; foo = safeWrapMethod(foo, "foo");
@Param: fn The function pointer/object to wrap.
@Param: name A string containing the name of fn as you wish it to be displayed in the call stack.
@Return: The method/function fn wrapped in an error handler.
*/
function safeWrapMethod (fn, name)
{ 
  try
  {
    return function ()
    { /* Wrapper added by safeWrapMethod */
      try
      {
        return fn.apply(this, arguments);
      }
      catch (e)
      {
        throw wrapError(e, name);
      }
    };
  }
  catch (e)
  {
    throw wrapError(e, "ErrorHelpers.safeWrapMethod");
  }
}

/**
@Description: Wraps every method in an object with an error handler. Affects the 
  instance of the object, but does not alter the underlying behavior of the methods.
@Param: o The class instance (object) to wrap.
@Param: name A string containing the name of the class. Method names will show as 
  "name.methodName" in an error's stack trace.
*/
function safeWrapClass (o, name)
{
  for (var m in o)
  {
    if (typeof(o[m]) === "function")
    {
      o[m] = safeWrapMethod(o[m], name + "." + m);
    }
  }
}; safeWrapClass = safeWrapMethod(safeWrapClass, "ErrorHelpers.safeWrapClass");


// Example Usage
function Foo() { safeWrapClass(this, "Foo"); }; Foo = safeWrapMethod(Foo, "Foo.ctor");
Foo.prototype.a = function () { throw new Error("oh noes!"); };
Foo.prototype.b = function () { this.a(); }
Foo.prototype.c = function () { this.b(); }

try
{
  var f = new Foo();
  f.c();
}
catch (e)
{
  var msg = e.message;
  if (e.stackTrace) { msg += "\r\n\r\nstackTrace: " + e.stackTrace.join("\r\n\tat "); }
  alert(msg);
  /*
  oh noes!
  
  stackTrace: Foo.a
    at Foo.b
    at Foo.c
  */
}