JS Error Handling
Todays Menu
- Error Object Definition
- Error Best Practices
- Extending the Error Object
- Practical uses in Node.js
- Using Errors at your API
The Error Constructor
new Error([message[, fileName[, lineNumber]]])
function equals(a, b) {
if (a !== b) {
throw new Error('Values are not equal');
}
}
Error Properties
Standard
- message The error message.
- name The error name.
Mozilla (node.js)
- fileName Path to file that raised the error.
- lineNumber The line number in the file that raised the error.
- columnNumber The col number.
- stack The error execution stack.
Error Methods
- toString() Returns a string representing the Error Object, overrides the Object.prototype.toString() method.
Error Types
EvalError Creates an instance representing an error that occurs regarding the global function eval().
InternalError Creates an instance representing an error that occurs when an internal error in the JavaScript engine is thrown. E.g. "too much recursion".
RangeError Creates an instance representing an error that occurs when a numeric variable or parameter is outside of its valid range.
ReferenceError Creates an instance representing an error that occurs when de-referencing an invalid reference.
SyntaxError Creates an instance representing a syntax error that occurs while parsing code in eval().
TypeError Creates an instance representing an error that occurs when a variable or parameter is not of a valid type.
URIError Creates an instance representing an error that occurs when encodeURI() or decodeURI() are passed invalid parameters.
Javascript Error Best Practises
General Advice
Always be using Error Objects
More Specifically
- In your [node.js] callbacks
- In error events you emit
- In your API (normalize)
- Throw in your Promises
Extending Error
Your own Error Objects
Classical Inheritance?
var util = require('util');
var CustomError = function() {
Error.apply(this, arguments);
this.customProp = true;
};
util.inherits(CustomError, Error);
console.log(customError.message); // undefined
console.log(customError.stack); // empty response
console.log(customError instanceof Error); // true
console.log(Object.keys(customError)); // ['customProp']
What happened here?
var util = require('util');
var CustomError = function() {
Error.apply(this, arguments);
this.customProp = true;
};
util.inherits(CustomError, Error);
Error is a function that returns a new Error object and does not manipulate this in any way
How to extend Error (node.js)
var util = require('util');
var CustomError = function(message) {
Error.captureStackTrace(this, this.constructor);
this.name = 'CustomError';
this.message = message;
};
util.inherits(CustomError, Error);
- instanceof Error works
- Stack traces work as expected
- Can extend itself
- captureStackTrace() is v8 specific
- For web replace with local throw
How to extend Error (web)
var util = require('util');
var CustomError = function(message) {
// Use V8's native method if available, otherwise fallback
if ('captureStackTrace' in Error) {
Error.captureStackTrace(this, CustomError);
} else {
this.stack = (new Error()).stack;
}
this.name = 'CustomError';
this.message = message;
};
util.inherits(CustomError, Error);
- instanceof Error works
- Stack traces have actual file on second line
- Can extend itself
Errors in Node.js
"Signing" Errors
Errors in Node.js
errors.DatabaseError = function(message) {
Error.captureStackTrace(this, this.constructor);
this.name = 'AcmeDatabaseError';
this.message = message;
// custom props
this.error = true;
};
util.inherits(errors.DatabaseError, Error);
Augmented Errors
Errors in Node.js
var appError = require('app-errors');
// ... //
User.prototype.hasPrivilege = function(userId, privilege, cb) {
this.fetchUser(userId, function(err, udo) {
if (!udo) {
var err = new appError.EmptyResultsError('User not found');
err.userId = userId;
cb(err);
return;
}
// ... //
});
};
Catch Specific Errors
Errors in Node.js
try {
myroutine(); // may throw three types of exceptions
} catch (ex) {
if (ex instanceof TypeError) {
} else if (ex instanceof RangeError) {
} else if (ex instanceof EvalError) {
} else {
logMyErrors(ex);
}
}
Using Errors on API
how to work with express
The Overview
Using Errors on API
- Create custom Errors with an httpCode or similar attribute, set to 500 by default.
- Throw them or augment existing Error objects by defining the httpCode.
- Create an express error middleware handling those errors.
- Pipe all error handling to next
Pipe Errors to next
Using Errors on API
UserCtrl.prototype.fetchUser = function(req, res, next) {
this.userEnt.readOne(req.param.userId)
.then(res.json)
.catch(next);
};
Express Error Handler
Using Errors on API
var customErrorHandler = function (err, req, res, next) {
var httpCode = 500;
httpCode = err.httpCode || httpCode;
res.status(httpCode);
// figure out what the client accepts
if (helpers.isRequestJson(req)) {
res.json(error);
} else {
res.render('error/' + error.httpCode, {error: error});
}
};
// Express error handler must always be last
// in all of your middleware
app.use(customErrorHandler);
Thank you
Questions?
JS Error Handling
By thanpolas
JS Error Handling
- 1,059