Throwing custom exceptions in Javascript. Which style to use? - javascript

Douglas Crockford recommends doing something like this:
throw {
name: "System Error",
message: "Something horrible happened."
};
But you could also do something like this:
function IllegalArgumentException(message) {
this.message = message;
}
throw new IllegalArgumentException("Argument cannot be less than zero");
and then do:
try {
//some code that generates exceptions
} catch(e) {
if(e instanceof IllegalArgumentException) {
//handle this
} else if(e instanceof SomeOtherTypeOfException) {
//handle this
}
}
I guess you could include a type property in Crockford's implementation and then examine that instead of doing an instanceof. Is there any advantage from doing one versus the other?

Update 2022
If your environment supports ES6, you should use inheritance from Error class, as recommended by Mozilla:
class IllegalArgumentException extends Error {
// ...
}
This is also the most upvoted answer in What's a good way to extend Error in JavaScript?.
Pre-ES6 (original answer)
Also pre-ES6 environments provide the Error class as basis for exceptions. It already allows you to define a message, but also provides a useful stack property to track down the context of the exception.
You can create your own exception type by using prototypical inheritance. There are already several stackoverflow discussions (for example: here), how to do this properly. However, I had to dig a little bit until I found the correct and modern approach. Please be aware that the approach that is suggested in the Mozilla documentation (see above) is not liked by the stackoverflow community. After a lot of reading I came out with that approach for inherit from Error.prototype:
function IllegalArgumentException(sMessage) {
this.name = "IllegalArgumentException";
this.message = sMessage;
this.stack = (new Error()).stack;
}
IllegalArgumentException.prototype = Object.create(Error.prototype);
IllegalArgumentException.prototype.constructor = IllegalArgumentException;

I am in favor of the second one since it is more reusable in terms of code purity. To be precise, if I am about to throw the same exception (even the same exception type with a different message) on several places, my code would get messy (immense) with the first approach.

Related

JavaScript/NodeJs Exception Handling

I'm confused how to properly catch JavaScript exceptions. I have a background as a Java Dev, so much of what I know about error handling comes from it.
I'm using sequelize for persistence, so messing around with it, I found an example on the web:
try {
//do sequelize stuff
} catch (error){
switch (error.name) {
case 'SequelizeUniqueConstraintError':
//do something
break;
case 'SequelizeValidationError':
//do something else
break;
default:
//do panic stuff
}
}
Well... that encouraged me to take a look inside sequelizer's source code...
What is thrown, is basically that:
class UniqueConstraintError extends ValidationError {
constructor(options) {
options = options || {};
options.parent = options.parent || { sql: '' };
options.message = options.message || options.parent.message || 'Validation Error';
options.errors = options.errors || {};
super(options.message, options.errors);
this.name = 'SequelizeUniqueConstraintError';
this.errors = options.errors;
this.fields = options.fields;
this.parent = options.parent;
this.original = options.parent;
this.sql = options.parent.sql;
}
}
hmmm... Interesting.... why would an exception have a name, besides already having a type?
So I changed my code to deal with the types themselves instead of the names, and it ended up like this:
try {
//do sequelize stuff
} catch (error){
if (error instanceof UniqueConstraintError) {
//do something
} else if (error instanceof ValidationError) {
//do something else
} else {
//do panic stuff
}
}
Needless to say, both work just fine.
Is there something I'm missing here? Am I following the wrong tutorials?
Witch solution would be the 'par excellence' in order to deal with multiple possible exceptions being thrown in modern JavaScript?? (witch may be not necessarily any of the two I've presented here)
Thanks.
Why would an exception have a name, besides already having a type?
For the same reason as using error codes: they serialise well and don't require a reference to the class. Also in some rare occasions (that should be avoided) you might end up with multiple copies of the library being loaded, which define multiple distinct classes with the same name. Checking the .name string still works, using instanceof only works if you reference the same class.
Which solution would be the 'par excellence' in order to deal with multiple possible exceptions being thrown in modern JavaScript?
If instanceof works for you, there's nothing wrong with using it - it's perfectly idiomatic. It's just that some programmers prefer a more defensive style that's more resilient in the face of bugs. Using string constants has its own set of problems, e.g. being prone to misspelling and API incompatibility.
Checking the value of a name property may be considered safer and/or simpler because:
for example, an instance of UniqueConstraintError is also an instance of ValidationError because the former extends the latter, so the order of the instanceof checks is crucial, and easy to get wrong.
for example, instanceof UniqueConstraintError may return false if the instance originated from a different execution context with its own global scope, such as that of an iframe.
If you are happy that neither of these reasons is pertinent then instanceof is more idiomatic and the better choice in my opinion.

Typescript - Extending Error class

I'm trying to throw a custom error with my "CustomError" class name printed in the console instead of "Error", with no success:
class CustomError extends Error {
constructor(message: string) {
super(`Lorem "${message}" ipsum dolor.`);
this.name = 'CustomError';
}
}
throw new CustomError('foo');
The output is Uncaught Error: Lorem "foo" ipsum dolor.
What I expect: Uncaught CustomError: Lorem "foo" ipsum dolor.
I wonder if that can be done using TS only (without messing with JS prototypes)?
Are you using typescript version 2.1, and transpiling to ES5? Check this section of the breaking changes page for possible issues and workaround: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
The relevant bit:
As a recommendation, you can manually adjust the prototype immediately after any super(...) calls.
class FooError extends Error {
constructor(m: string) {
super(m);
// Set the prototype explicitly.
Object.setPrototypeOf(this, FooError.prototype);
}
sayHello() {
return "hello " + this.message;
}
}
However, any subclass of FooError will have to manually set the prototype as well. For runtimes that don't support Object.setPrototypeOf, you may instead be able to use __proto__.
Unfortunately, these workarounds will not work on Internet Explorer 10 and prior. One can manually copy methods from the prototype onto the instance itself (i.e. FooError.prototype onto this), but the prototype chain itself cannot be fixed.
The problem is that Javascript's built-in class Error breaks the prototype chain by switching the object to be constructed (i.e. this) to a new, different object, when you call super and that new object doesn't have the expected prototype chain, i.e. it's an instance of Error not of CustomError.
This problem can be elegantly solved using 'new.target', which is supported since Typescript 2.2, see here: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html
class CustomError extends Error {
constructor(message?: string) {
// 'Error' breaks prototype chain here
super(message);
// restore prototype chain
const actualProto = new.target.prototype;
if (Object.setPrototypeOf) { Object.setPrototypeOf(this, actualProto); }
else { this.__proto__ = actualProto; }
}
}
Using new.target has the advantage that you don't have to hardcode the prototype, like some other answers here proposed. That again has the advantage that classes inheriting from CustomError will automatically also get the correct prototype chain.
If you were to hardcode the prototype (e.g. Object.setPrototype(this, CustomError.prototype)), CustomError itself would have a working prototype chain, but any classes inheriting from CustomError would be broken, e.g. instances of a class VeryCustomError < CustomError would not be instanceof VeryCustomError as expected, but only instanceof CustomError.
See also: https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200
As of TypeScript 2.2 it can be done via new.target.prototype.
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#example
class CustomError extends Error {
constructor(message?: string) {
super(message); // 'Error' breaks prototype chain here
this.name = 'CustomError';
Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
}
}
It works correctly in ES2015 (https://jsfiddle.net/x40n2gyr/). Most likely, the problem is that the TypeScript compiler is transpiling to ES5, and Error cannot be correctly subclassed using only ES5 features; it can only be correctly subclassed using ES2015 and above features (class or, more obscurely, Reflect.construct). This is because when you call Error as a function (rather than via new or, in ES2015, super or Reflect.construct), it ignores this and creates a new Error.
You'll probably have to live with the imperfect output until you can target ES2015 or higher...
I literally never post on SO, but my team is working on a TypeScript project, and we needed to create many custom error classes, while also targeting es5. It would have been incredibly tedious to do the suggested fix in every single error class. But we found that we were able to have a downstream effect on all subsequent error classes by creating a main custom error class, and having the rest of our errors extend that class. Inside of that main error class we did the following to have that downstream effect of updating the prototype:
class MainErrorClass extends Error {
constructor() {
super()
Object.setPrototypeOf(this, new.target.prototype)
}
}
class SomeNewError extends MainErrorClass {}
...
Using new.target.prototype was the key to getting all of the inheriting error classes to be updated without needing to update the constructor of each one.
Just hoping this saves someone else a headache in the future!
I ran into the same problem in my typescript project a few days ago. To make it work, I use the implementation from MDN using only vanilla js. So your error would look something like the following:
function CustomError(message) {
this.name = 'CustomError';
this.message = message || 'Default Message';
this.stack = (new Error()).stack;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
throw new CustomError('foo');
It doesn't seem to work in SO code snippet, but it does in the chrome console and in my typescript project:
I was having this problem in a nodejs server. what worked for me was to transpile down to es2017 in which these issues seems to be fixed.
Edit tsconfig to
"target": "es2017"
Try this...
class CustomError extends Error {
constructor(message: string) {
super(`Lorem "${message}" ipsum dolor.`)
}
get name() { return this.constructor.name }
}
throw new CustomError('foo')

Combine Array with Error in a single type

I have a promise-based library (for Node.js 0.10 - 6.x) with a method that rejects with an Array.
When using Bluebird it results in a warning: a promise was rejected with a non-error.
Wrapping the array into a custom error type is easy, but I want to avoid breaking the library's backward compatibility.
Is it possible to implement such an object that could be used as an array, while being seen by Bluebird as an Error object at the same time?
extras
When inheriting from Error I use the following helper for compatibility with Node.js 0.10 - 0.12:
function inherits(child, parent) {
child.prototype.__proto__ = parent.prototype;
}
And looking at the Bluebird source, maybe there is a way to circumvent its verification somehow:
Promise.prototype._rejectCallback =
function(reason, synchronous, ignoreNonErrorWarnings) {
var trace = util.ensureErrorObject(reason);
var hasStack = trace === reason;
if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
var message = "a promise was rejected with a non-error: " +
util.classString(reason);
this._warn(message, true);
}
this._attachExtraTrace(trace, synchronous ? hasStack : false);
this._reject(reason);
};
Javascript don't permits real multiple prototypal inheritance.
You can "extend" Error but the subclass can't be both instanceof an Error and an Array.
If Bluebird use duck-typing you can try to subclass Array object and simulate Error behavior (interface and and properties), but this depends strongly of Bluebird error-check implementation.
I think is better and robust to wrap the array value into an Error property/attribute.
So long as your environment allows subclassing Error, yes!
I asked about something similar while extending errors to create my own subtypes, which is essentially what you want to do. In fact, I've done something similar to create HTTP-specific errors that include the response's status code.
Assuming your environment does allow class SubError extends Error (and there is a workaround if not), you simply do:
class ErrorWithData {
constructor(msg, data = []) {
super(msg); // this changes with the workaround
this._data = [].concat(data); // make a copy for safety's sake
}
get data() {
return this._data;
}
}
If you're in an older browser that does not allow you to subclass Error, you can use the shim class from #Mosho's answer and replace extends Error in that example with extends ErrorClass.
NodeJS will allow you to extends Error from v4 and on, with v6 having correct/full support for it. Earlier versions require Mosho's workaround.

Replacement for Prototype.js Class system

We have a set of classes created that depend on Prototype's Class implementation (and some Object.extend).
The problem is prototype is creating trouble when integrating with the rest of our applications (even with "noconflict" adapters and the such).
Does anybody know of a compatible Class implementation that does not mess with the global scope? Or has anybody been able to "extract" Prototype's to use it alone?
I wrote one a couple of years back (I should go revisit it, and give it a proper name) because I didn't like Prototype's handling of calling methods on the "superclass", which involves creating a function every time an overridden method is called (yes, really). It's very similar to Prototype's except for how you make supercalls; you can readily drop it in and search for super in your code and change it up. My implementation also makes it a bit easier to use named functions rather than anonymous ones, which is useful for many reasons, not least because it helps your tools help you. It also makes private "class" methods trivial. Details below.
But you don't have to use mine. There are other options that will require slightly more work to migrate your code to, but probably not a lot more:
John Resig's simple inheritance
Dean Edwards' mechanism
My issue with both of them is that they use function decompilation (so does Prototype's Class stuff), and function decompilation (e.g., calling toString on a function) has never been standardized and does not work on some mobile browsers. Resig's mechanism continues to work if function decompilation doesn't work, but it adds overhead to every method in that case (rather than only ones that make supercalls). My mechanism doesn't use function decompilation at all, adds no overhead to method calls, and even makes supercalls highly-efficient.
If you use my mechanism and your Prototype code looks like this:
var SuperThingy = Class.create({
foo: function(arg) {
console.log("SuperThingy: " + arg);
this._pseudoPrivate();
},
_pseudoPrivate: function() {
console.log("I'm not really private.");
}
});
var Thingy = Class.create(SuperThingy, {
foo: function(super, arg) {
console.log("Thingy: " + arg);
super(arg);
}
});
You can make minimal changes:
var SuperThingy = Helper.makeClass({
foo: function(arg) {
console.log("SuperThingy: " + arg);
this._pseudoPrivate();
},
_pseudoPrivate: function() {
console.log("I'm not really private.");
}
});
var Thingy = Helper.makeClass(SuperThingy, {
foo: function(arg) {
console.log("Thingy: " + arg);
this.callSuper(arguments, arg);
}
});
...or you can make slightly larger changes and get the benefit of a speed increase (callSuper uses arguments.callee, which is slow), properly-named functions (for debugging and such), and truly private functions:
var SuperThingy = Helper.makeClass(function() {
function SuperThingy_foo(arg) {
console.log("SuperThingy: " + arg);
trulyPrivate.call(this);
}
function trulyPrivate() {
console.log("I'm truly private.");
}
return {foo: SuperThingy_foo};
});
var Thingy = Helper.makeClass(SuperThingy, function() {
function Thingy_foo(arg) {
console.log("Thingy: " + arg);
foo.$super.call(this, arg);
}
return {foo: Thingy_foo};
});
The Prototype source tries to be modular so you can download lang/class.js separately. However a quick glance at the code shows it depends on functions from lang/array.js, lang/object.js, lang/function.js - it would be safer to grab prototype.js and all of the lang directory. That gives you the core of Prototype without the conflicting DOM stuff.
I too find the Class class too useful to do without. I was recommended to try Sugar which is nice but still has no inheritence. It seems the only real alternative currently is MooTools' class.
You should have a look at :
MyJS class system
I think you will enjoy !
After trying out ComposeJS, I couldn't find a way to invoke superclass constructors explicitly (they are invoked automatically), so I had to abandon it. I finally settled on JsFace which has many features (inheritance, mixins, static properties, AOP), although a slightly weird syntax to invoke the super class constructor: this.$class.$super.call(args). It also seems to be the fastest implementation, according to its website and also this benchmark, totally blowing away the Resig implementation, which is quite slow. The caveat to watch out for is is that this.$class.$super is always the super class of the final child class, so you may need to do something like this:
var C = Class(A, {
constructor: function (x) {
C.$super.call(this, x);
},
...
}
instead of
var C = Class(A, {
constructor: function (x) {
this.$class.$super.call(this, x);
},
...
}
which is like the examples, if you have multiple levels of inheritance, otherwise you'll get an infinite recursion.

Object-Oriented JavaScript tools

I have been working on the user interface of my website (www.swalif.com: do use chrome to translate if you like to). Not being familiar with jQuery I started off with JavaScript and now the file is huge: about 1000 lines of code. Furthermore the code is getting complex to handle and change.
Therefore I was looking for a way I could approach this problem in an object oriented manner that would result in a clean, re-usable system with a good architecture. Also would be nice to use features as provided by JQuery to keep the code small.
The problem is that there are a lot of tools out there and I cannot decide which one to invest time into to accomplish this task. e.g. mootools, prototype, jQuery, etc. So I need someone to lead me in the right direction.
This is our website www.swalif.com. Any other suggestion are also welcome.
For object-oriented javascript development I would recommend John Resig's Simple javascript Inheritance. It is a tiny bit of javascript that allows you to define classes, derive from base classes and override methods.
var Person = Class.extend({
init: function(isDancing){
this.dancing = isDancing;
},
dance: function(){
return this.dancing;
}
});
var Ninja = Person.extend({
init: function(){
this._super( false );
},
dance: function(){
// Call the inherited version of dance()
return this._super();
},
swingSword: function(){
return true;
}
});
var p = new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class
I think you'd be better off with a framework that actively developed and is build with OOP with extendability, reusability, mixings, mutators in mind.
This is exactly why MooTools was created.
That said, if you're not familiar with JS, it would be pretty difficult to grasp MooTools, since it's not a framework for beginners. Then again, if you grasp the notion of OOP, you should be ok.
Don't actually use a framework to implement your OOP. You get a much richer understanding of Javascript as a language when you deal with the nitty gritty of using Javascript's very flexible function prototype system to implement OOP-like operations.
Read about it here: http://phrogz.net/JS/Classes/OOPinJS.html.
If you only need to organize your code and don't need libraries you may use http://code.google.com/p/joose-js/. Otherwise use the oop model of the library you are using.
Simple example
Module("Test", function (m) {
Class("Point", {
has: {
x: {
is: "rw",
init: 0
},
y: {
is: "rw",
init: 0
}
},
methods: {
clear: function () {
this.setX(0);
this.setY(0);
}
}
})
})

Categories