Warning: I would not recommend the original answer using domains, domains are being deprecated in the future, I had a lot of fun writing the original answer but I no longer believe it is too relevant. Instead - I suggest using event emitters and promises that have better error handling - here is the below example with promises instead. The promises used here are Bluebird:
Promise.try(function(){
throw new Error("Something");
}).catch(function(err){
console.log(err.message); // logs "Something"
});
With a timeout (note that we have to return the Promise.delay):
Promise.try(function() {
return Promise.delay(1000).then(function(){
throw new Error("something");
});
}).catch(function(err){
console.log("caught "+err.message);
});
With a general NodeJS funciton:
var fs = Promise.promisifyAll("fs"); // creates readFileAsync that returns promise
fs.readFileAsync("myfile.txt").then(function(content){
console.log(content.toString()); // logs the file's contents
// can throw here and it'll catch it
}).catch(function(err){
console.log(err); // log any error from the `then` or the readFile operation
});
This approach is both fast and catch safe, I recommend it above the below answer which uses domains that are likely not here to stay.
I ended up using domains, I have created the following file I called mistake.js
which contains the following code:
var domain=require("domain");
module.exports = function(func){
var dom = domain.create();
return { "catch" :function(errHandle){
var args = arguments;
dom.on("error",function(err){
return errHandle(err);
}).run(function(){
func.call(null, args);
});
return this;
};
};
Here is some example usage:
var atry = require("./mistake.js");
atry(function() {
setTimeout(function(){
throw "something";
},1000);
}).catch(function(err){
console.log("caught "+err);
});
It also works like normal catch for synchronous code
atry(function() {
throw "something";
}).catch(function(err){
console.log("caught "+err);
});
I would appreciate some feedback on the solution
On a side note, in v 0.8 apparently when you catch the exception in the domain it still bubbles to process.on("uncaughtException")
. I dealt with this in my process.on("uncaughtException")
with
if (typeof e !== "object" || !e["domain_thrown"]) {
However, the documentation suggests against process.on("uncaughtException")
any way