Edit:Edit: Please read comments. It turns out this only works well in V8 (Chrome / Node.JS) My intent was to provide a cross-browser solution, which would work in all browsers, and provide stack trace where support is there.
Fully capableEdit: I made this Community Wiki to allow for more editing.
Solution for V8 (Chrome / Node.JS), works in Firefox, and can be modified to function mostly correctly in IE. (see end of post)
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype // Make this an instanceof Error.
Error.call(this) // Does not seem necessary. Perhaps remove this line?
Error.captureStackTrace(this, this.constructor) // Creates the this.stack getter
this.name = this.constructor.name; // Used to cause messages like "UserError: message" instead of the default "Error: message"
this.message = message; // Used to set the message
}
Original post on "Show me the code !"
Short version:
function UserError(message) {
this.constructor.prototype.__proto__ = Error.prototype
Error.captureStackTrace(this, this.constructor)
this.name = this.constructor.name
this.message = message
}
I keep this.constructor.prototype.__proto__ = Error.prototype
inside the function to keep all the code together. But you can also replace this.constructor
with UserError
and that allows you to move the code to outside the function, so it only gets called once.
If you go that route, make sure you call that line before the first time you throw UserError
.
That caveat does not apply the function, because functions are created first, no matter the order. Thus, you can move the function to the end of the file, without a problem.
Browser Compatibility
Works in Firefox and Chrome (and Node.JS) and fills all promises.
Internet Explorer fails in the following
Errors do not have
err.stack
to begin with, so "it's not my fault".Error.captureStackTrace(this, this.constructor)
does not exist so you need to do something else likeif(Error.captureStackTrace) // AKA if not IE Error.captureStackTrace(this, this.constructor)
toString
ceases to exist when you subclassError
. So you also need to add.else this.toString = function () { return this.name + ': ' + this.message }
IE will not consider
UserError
to be aninstanceof Error
unless you run the following some time before youthrow UserError
UserError.prototype = Error.prototype