Forrest L Norvell & Domenic Denicola, nodeconf 2013
uncaughtException is gross
var domain = require("domain");
var d = domain.create();
d.on("error", function (error) {
  console.error("Well, this sucks: %s", error.message);
  process.exit(1);
});
d.run(function () {
  // do error-prone stuff here
});
        
var http = require('http'), domain = require('domain');
http.createServer(function (req, res) {
  var d = domain.create();
  d.on("error", function (error) {
    res.writeHead(500, {'Content-Type': 'text/plain'});
    res.end('Couldn\'t fulfill request because of an error: ' +
            error.message);
  });
  d.run(function () {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
  });
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
        domain.add(emitter) binds an EventEmitter to a domain.
var http = require('http'), domain = require('domain');
http.createServer(function (req, res) {
  var d = domain.create();
  d.on("error", function (error) { /* ... */ });
  d.add(req);
  d.add(res);
  d.run(function () { /* ... */ });
}).listen(1337, '127.0.0.1');
        
app.use(function (req, res, next) {
  var d = domain.create();
  d.on("error", next);
  d.run(next);
});
// all the other middlewares in the stack
app.use(express.errorHandler());
        One nice thing is that the built-in error handler respects the
        Accept header coming from the user agent.
var defaultHandler = express.errorHandler();
app.use(function (error, req, res, next) {
  if (domain.active) {
    domain.active.emit("error", error);
  } else {
    defaultHandler(error, req, res, next);
  }
});
app.get("/crashy", function (req, res) {
  var d = domain.create();
  d.on("error", function (error) {
    res.send(500, {"error": error.message});
  });
  d.run(function () { throw new Error("oops"); });
});
        domain.bind(fn) ensures that any errors inside
          fn are trapped by the domain.domain.intercept(fn) is the same, but takes a
          conventional Node callback and traps the error parameter in the
          domain. The parameter must be an instance of
          Error.
var d = domain.create();
// ...
fs.readFile("filename.txt", function (error, data) {
  if (error) return d.emit("error", error);
  // do stuff with contents
});
        becomes
var d = domain.create();
// ...
fs.readFile("filename.txt", d.intercept(function (data) {
  // do stuff with contents
}));
        domain.bind(callback) (or
          domain.intercept(callback)) to trap errors in your
          code.domain.run(), but you'll still want to explicitly bind
          your application callbacks to the lexically closest domain
var pool;
var poolD = domain.create(); poolD.run(function () {
  pool = new mydb.Pool();
  poolD.on("error", function (error) {
    console.error("Connection pool exploded with '%s'. Trying clean shutdown.", error.message);
    pool.flush();
    pool.close(function () { process.exit(1); });
  });
});
var client = require("./mydb/client.js")(pool);
function processUsers(error, users) { /* do stuff */ }
function getUsers() {
  var d = domain.create();
  d.on("error", function (error) { /* custom error-handling */ });
  client.getUsers(d.bind(processUsers));
}
        domain.run(), domain.bind(),
          domain.add(), and domain.intercept() you can
          handle all three of the common mechanisms for signaling errors in node
          (callback convention, error events, and try/catch).domain.enter() and domain.exit() are the primitives
          that set up and tear down domains.domain.exit() gets called both
          when errors are trapped and when domains are exited normally.domain.enter() and domain.exit() are the primitives
          domain.bind() is a wrapper around
          Function.bind(), domain.enter(), and
          domain.exit():
        
Domain.prototype.bind = function (callback) {
  return function () {
    this.enter();
    callback();
    this.exit();
  }.bind(this);
};
Domain.prototype.intercept = function (callback) {
  return function (error) {
    if (error) return this.emit("error", error);
    this.enter();
    callback.apply(null, Array.prototype.slice.apply(arguments, 1));
    this.exit();
  }.bind(this);
}
          domain.run() is just an immediately invoked
          version of domain.bind().domain.enter() pushes a domain on the stack,
          domain.exit() pops that domain and all the domains
          above it on the stackthrow
          pops multiple stack frames in traditional exception handlingprocess.domain and domain.activeprocess.domain in code where
          domains are optional or can be used opportunisticallydomain.active