Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error Handling in Sails.js

Tags:

sails.js

I am just starting using Sails.js and it's an amazing framework. But I've met some situation and I cannot find solution by Google so I came here for help.

I have a controller to connect to another remote service with very old-designed API full of XML response and inconsistency, wrapping that service in simple and clean APIs. So I have some routers like:

list: function(req, res) {
    params = {
        ...
    }

    FooService.request(data, function(error, response) {
        res.send(response)
    })

    process.once('uncaughtException', function(err) {
        res.send(500, '[Foo] ' + err);
    });
},

The 'process.once' is for async exceptions which may raised in the FooService.request process. I know this is bad code and my question is: how to handle such situation more Sails.js way?

In Node.js we have Domain and connect-domain, which are designed for such problems. Because Sails.js is basically Express, which can facilitate connect-domain very well, I think there may be some idiomatic way to do that.

I've tried adding this in config/local.js:

module.exports = {
    ...
    express: {
        customMiddleware: function(app) {
            console.log('Custom middleware config called')

            var domain = require('connect-domain')
            app.use(domain())
            .use(function(err, req, res, next) {
                console.log('Error catched!')
                res.send(500, '[Foo] ' + err)
            })
        }
    }
};

When un-catched exception occurred, it will not crash server and error 500 being returned to client side ('app.use(domain())' works). But the custom error handler does not called. Have no idea why.

like image 200
Neo Avatar asked Oct 21 '22 13:10

Neo


1 Answers

If you're in control of the FooService code, then the best option is to handle all errors that happen there by calling the callback for FooService.request early with the error, and then using res.serverError or some other response in your controller:

FooService.request(data, function(error, response) {
    if (error) {return res.serverError(errror);}
    res.send(response)
});

If the FooService is using packages that you don't control, which may themselves throw errors inside of async code that they aren't catching (bad code!) then another good option is to use Node's error domains. See this answer for an example of someone doing a quick wrapper to use domains to catch errors in asynchronous code.

like image 123
sgress454 Avatar answered Nov 24 '22 01:11

sgress454