I'm not at my first express.js application, although I have still to figure out the most robust way to handle errors.
Since io.js is reality from a couple months I'm using native Promises to help myself with asyncronicity, the following code reflects that.
My error-handling middleware is as following:
router.use(function (err, req, res, next) {
// in case err.custom is present, means is an "handled" Error, created by developers
if (!!err.custom) {
return res.status(err.code).json(err.message);
}
if (err instanceof Error) {
console.error(err.stack);
return res.status(500).send('Runtime Error'); // should be reported!
}
// last but not least, validation error
res.status(400).send(err);
});
An example controller is written like this:
function callService1 (param1) {
return new Promise(function (resolve, reject) {
service.call(param1, function (err, data) {
if (!!err) return reject(err); // this is an Error object?? not sure!
if (!!data.handledError) { // this is an handled Error to the user, not 500
return reject({ custom: true, status: 403, message: 'service1 tells you that myCoolParam is not valid' });
}
resolve(data);
});
};
}
function callService2 (dataFromParam1) {
return new Promise(function (resolve, reject) {
// something here
});
}
// this is the API "controller"
module.exports = function (req, res, next) {
callService1(req.body.myCoolParam)
.then(callService2)
.then(function (service2Output) {
res.status(200).json({ message: 'everything went smooth!' });
})
.catch(next); // here is the catch-all errors
};
As you can see the express middleware looks quite tidy and elegant.
I usually handle all the interesting errors to the user in the rejects()
, some of them are called with an object where I tell the errorhandling middleware.
The problem is service
from the example is a 3rd-party library.
Those libraries some times returns a string, sometime an object (from an external API), sometimes a javascript Error.
Currently I cannot handle custom javascript Objects, moreover if I want to throw an error 500 to the user I have to do reject(new Error(err));
but sometimes this err
is an object, resulting in:
Error: [object Object]
at errorHandler (awesomeapi\postsomething.js:123:16)
at IncomingMessage.<anonymous> (node_modules\mandrill-api\mandrill.js:83:24)
at emitNone (events.js:72:20)
at IncomingMessage.emit (events.js:163:7)
at _stream_readable.js:891:16
at process._tickCallback (node.js:337:11)
This is not cool at all, and I would really like to figure out a way to handle gracefully those errors, without adding code (if possible), since I find this syntax quite elegant and concise.