There are lots of patterns for various styles of object-oriented JavaScript. They range from the simple few-liner patterns to the complex libraries with lots of syntax sugar. Also, this great book on OO JS by Nicholas Zakas is a must-read.

However, I have to admit that I am typically not a fan of most Object-Oriented JavaScript patterns. Well, I should clarify that to say, I’m not a fan of inheritance patterns in JavaScript (or any interpreted language for that matter).

The reason is usually performance related, and also because most scripting languages do a poor job of supporting the right syntax to make this efficient (hence the aforementioned libraries that go to great lengths to support it for you). Also, JavaScript has this really annoying habit of losing the “this” binding all too easily, which makes properly coding with “this” to be more a pain than most would like.

In my opinion, I shouldn’t have to think so hard about a programming construct that it actually gets in the way of what I want to do. Granted, maybe it’s a perpetual cycle, because I’ve never been fond of OOJS, nor had much use for it, that I’ve not been exposed enough to where it just comes naturally for me to think that way.

By contrast, I do get JavaScript closures, in a deep and profound way that makes me all warm and fuzzy inside. So it follows naturally that I use them all the time, for OO patterns such as encapsulation. I find it to be absolutely invaluable, and I have no trouble coding them almost in my sleep.

Many others however consider closures to be confusing and even somewhat mystical, almost the same way that subtle differences between “references” and “pointers” in C++ have tripped up many a developer.

Anyway, listening recently to Alex Sexton speak about such things in his “Superclassy Inheritance in JavaScript” talk from Developer Day (Austin), I realized one area that I’ve always wanted to inject a little OO (inheritance) into my JS — Error Handling.

All the world’s an error

I assume you are aware of the fact that JavaScript has errors! Almost every page on the web has, at one time or another, thrown frustrating errors at unsuspecting visitors. If you are blissfully unaware of such things because your browser hides them from you, I’m sure you’ve at least missed out on some intended interaction experience because of broken scripts at one point or another.

The reason JavaScript errors get thrown in our faces so often is that code is often not written in a robust manner. It’s written quickly or sloppily or just in best-case scenario world only. When an unexpected error condition occurs, and “noone” (ie, none of the script) is paying attention, the error bubbles all the way up to the browser, and everything stops. Talk about worst-case scenario.

Just try me

JavaScript has, for a long time, supported the “try/catch” paradigm (popular in other OO languages like C++ and Java), which is supposed to be a way to handle errors more robustly. The thought goes, if you “wrap” a try/catch clause around a potentially problematic set of code before you “try” it, you can “catch” an error on-the-fly that may occur, and respond in a more graceful way than just stopping and quitting.

For instance, you could try an alternate syntax for the offending statement, or at the very least, you could politely message to the user than an error happened and that they should refresh or try again later.

Those familiar with object-oriented programming know that the preferred pattern for how to handle errors in the bowels of a function or object is not to just quit, or return “0” or “-1″ (as was the style of old-school C programs, for instance). Instead, you should simply “raise” or “throw” an error, hopefully with some helpful info like why, and then let the originating code “catch” the error and correct as appropriate.

Example:

function doSomething(val) {
   if (val < 1) throw new Error("val should be greater than 1");
   ...
}

try {
   doSomething(0);
}
catch (err) {
   doSomething(1);
}

So, obviously in that trivial example it looks rather contrived. But, you should get the point: if necessary, throw an error somewhere, let somewhere else catch that error and proceed accordingly.

So, use try/catch everywhere, right?

To be sure, you should not write sloppy code and just assume that try/catch clauses will save the day. Not only will that style of coding lead to inefficient and bloated code, but also you are really abusing what the pattern was intended for: graceful error handling.

Nothing could be less graceful than a try/catch around every line of code, or worse yet, just one big try/catch wrapped around everything. You should design your code to be as robust as possible, and use try/catch clauses in specific areas where it will be helpful and more graceful than just dying in the code execution.

Then what?

I'm gonna skip forward and assume that you now understand how to properly and wisely use try/catch in your code. If you go and abuse it, don't come blaming me, 'cause I warned you.

So, the real problem with just the standard generic "Error" object in JavaScript is that it fails to give the "catching" code much good information about what kind of (or, why the) error occured. Imagine a function that can throw one of 4 different specific errors, as well as the occasional uncaught general exception. The single try/catch around that function call is going to have a really hard time deciding which of those 5 cases it was, and thus what to do about it.

That's why in more traditional languages like C++ and Java (and even Actionscript!), the pattern really says that you should create a specific typed error when you throw one manually. The "catching" code can then examine the type of what was caught, and act appropriately. Again, more graceful.

So now we see why I started talking about object-oriented inheritance at the top of the article... to accomplish all this pattern has to offer, we need a good/easy way to extend the built in native Error object in JavaScript, so that when we throw them, and other code catches them, it knows what kind of error was actually thrown.

What I'm going to present here should not at all be considered the only (or maybe even best) way to do this, but I'm quite happy with this pattern as it supports all the necessary requirements I had. Most specifically, it's a pattern of code you can put in place without using any other library/dependency, and once your "Custom Error" class (or classes) is/are in place, using them should be pretty straightforward and true to pure JavaScript coding. It also gives you some basic inheritance (prototypal) behavior to make code a little easier to maintain and extend.

Here's a custom error class that extends the native Error object with a custom field/method:

var MyError = (function() {
   function F(){}
   function CustomError() {
      // correct if not called with "new"
      var _this = (this===window) ? new F() : this,
          tmp = Error.prototype.constructor.apply(_this,arguments)
      ;
      for (var i in tmp) {
         if (tmp.hasOwnProperty(i)) _this[i] = tmp[i];
      }
      return _this;
   }
   function SubClass(){}
   SubClass.prototype = Error.prototype;
   F.prototype = CustomError.prototype = new SubClass();
   CustomError.prototype.constructor = CustomError;

   // add a custom method
   CustomError.prototype.CustomField1 = function(custom_1){
      if (custom_1 != null) this.custom_1 = custom_1;
      return this.custom_1;
   }

   return CustomError;
})();

I don't want to spend too much time explaining all the ins and outs of this code and how it does what it does. But I'll try to explain the most important things.

Firstly, how you use it:

function doSomething(val) {
   if (val < 1) {
      var err = new MyError("something");
      err.CustomField1("val was less than 1");
      throw err;
   }
   ...
}
...
try {
   doSomething(0);
}
catch (err) {
   if (err instanceof MyError) alert(err.CustomField1());
   else alert("A generic error occured.");
}

So, when an error/exception condition is detected, we instantiate a new MyError instance in the way you'd expect: var err = new MyError("something");. (NOTE: you don't have to use the "new" keyword, as the code has detection to correct for this if you forget it, but it's definitely better and more efficient if you do.)

Then, we call a custom method on our custom error instance, "CustomField1", and in this case, we pass in a value that gets set as a custom field/property on our instance. We could have just done err.custom_1 = "..."; but that's not very OO is it!?

Now, we simply "throw" the error object. You'll see that the function doSomething() is "try"d and thus the error we threw will be caught. Lastly, to distinguish between our custom error and a generic error thrown by the JS interpreter, we use the "instanceof" operator check.

Pretty cool huh? We created a custom "class" of "MyError" that extends from (and inherits behavior from) the native Error object, we added custom behavior to it, we created and threw the error, we caught it, and then we checked to make sure what we caught was the correct type of error.

Going further

Here is a demo of extending the Error object to create custom Error classes. The demo shows "MyError" extending "Error", and then "MoreMyError" in turn extending "MyError" and overriding some of its inherited functionality.

For reference (if you don't want to view-source on that demo), the source code for the demo is available on github.

Special thanks to John-David Dalton (and, as mentioned before, Alex Sexton), for inspiration and assistance in getting something like this to work properly. As I said, my OOJS kung fu is not as strong as it is with closures, but I'm happy that this is a good solid solution that I can now start using in my code. Hopefully it'll help you make better, more graceful error handling code for your JS projects.

This entry was written by getify , posted on Monday February 08 2010at 02:02 pm , filed under JavaScript and tagged , , . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

2 Responses to “HowTo: Custom “Error” types in JavaScript”

  • Kenneth Axi says:

    There is a small error in the demo code; The custom error object is never handling the errormessage created in the call:

    var err2 = MyError(“{custom MyError}”);

    When You then print err2.message, it shows up empty. This is because the message is never set in the constructor function.
    This can easily be changed to

    function CustomError(message) {
    this.message = message;
    ….
    }

    Then the message “{custom MyError}” will show up in the log / output.

  • Yuyu says:

    Better:

    var makeErrorType = function() {
    	var it = function(message) {
    		if (!(this instanceof it)) return new it(message);
    		this.message = message
    		this.stack = new Error(message).stack
    	}
    	it.prototype = Object.create(Error.prototype)
    	return it
    }
    

Leave a Reply

Consider Registering or Logging in before commenting.

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.