/opt/git/front-prod/server/pumps/message_template.js:71 name: this.peer.name, ^ TypeError: Cannot read property 'name' of undefined at MessageTemplate.toContact (/opt/git/front-prod/server/pumps/message_template.js:71:20) at /opt/git/front-prod/server/pumps/message_template.js:48:26 at fn (/opt/git/front-prod/node_modules/async/lib/async.js:579:34) at Object._onImmediate (/opt/git/front-prod/node_modules/async/lib/async.js:495:34) at processImmediate (timers.js:330:15)
/Users/laurent/dev/talk_domains/test.js:4 done(); ^ TypeError: undefined is not a function at null._onTimeout (/Users/laurent/dev/talk_domains/test.js:4:5) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
function doSomething(done) {
setTimeout(function () {
console.log('did something');
done();
}, 1000);
}
doSomething(/* missing */);
doSomething
(where the error is located). We'll talk about that in a minute./opt/git/front-prod/node_modules/longjohn/dist/longjohn.js:181 throw e; ^ Error: read ECONNRESET at errnoException (net.js:901:11) at onread (net.js:556:19)
When you don't listen to 'error' events, they turn into exceptions.
Pain level: 9
/10
Your app forgets about a connection and the browser loads forever:
function doSomethingElse(done) {
someBackend.load(function (err, data) {
if (err) {
console.log('Something happened', err);
// you forgot to call the callback
return;
}
done(null, data);
})
}
function doSomething(done) {
console.log('about to do something');
setTimeout(function () {
console.log('did something');
done();
}, 1000);
}
doSomething(/* missing */);
function doSomething(done) { console.log('about to do something'); setTimeout(function () { console.log('did something'); done(); }, 1000); } doSomething(/* missing */);
function doSomething(done) { console.log('about to do something'); setTimeout(function () { console.log('did something'); done(); }, 1000); } doSomething(/* missing */);
setTimeout
, the callback is just a parameter and is not executed. After that, the function returns and unwinds the stack.function doSomething(done) { console.log('about to do something'); setTimeout(function () { console.log('did something'); done(); }, 1000); } doSomething(/* missing */);
setTimeout
starts a new stack.
function doSomething(done) { try { setTimeout(function () { console.log('did something'); done(); }, 1000); } catch(e) { console.log('not executed'); } } doSomething(/* missing */);
setTimeout
executes. The try/catch
will not catch the exception.Added in node.js 0.8.0 (June 2012)
"a way to join multiple different IO actions, so that you can have some context when an error occurs."
The way I see it: the active domain is passed as a hidden parameter in function calls.
(at this point, I demoed the code)
After calling MySQL, we end up in a different domain.
We are not even able to send a 500 error to client.
preserveDomain
function preserveDomain(fun) {
var d = domain.active;
return function () {
var args = arguments;
d.run(function () {
fun.apply(null, args);
});
};
}
Catching error in usafe modules without patching them
domain.create().on('error', function (err) {
// handle error
}).run(unsafeModule);
var d = domain.create();
d.start = Date.now();
d.log = function (msg) {
console.log(Date.now() - d.start, msg);
};
domain.active
.
exports.wrapFetch = function (Resource, fetcher) {
var type = Resource.prototype.className;
return function (id, done) {
var d = domain.active,
key = type + '/' + id;
d.ensureNotGarbaged();
var cached = d.reqcache[key],
pending = d.pendings[key];
if (cached)
return done(null, cached);
if (pending)
return pending.push(done);
pending = [done];
d.pendings[key] = pending;
fetcher(id, function (err, resource) {
d.ensureNotGarbaged();
if (!err)
d.reqcache[key] = resource;
// destroy the pending list now in case the domain is garbaged by a callback
delete d.pendings[key];
// finally, notify all pending requests
_(pending).each(function (cb) {
cb(err, resource);
});
});
};
};
domain.active
if undocumented.Laurent Perrin
github.com/lperrin, @l_perrin
frontapp.com
(we're hiring)