Почему первый параметр?
Из-за асинхронного характера Node.js шаблон first-parameter-as-err стал общепризнанным соглашением для userland Node.js обработка ошибок .Это потому, что асинхронный:
try {
setTimeout(function() {
throw 'something broke' //Some random error
}, 5)
}
catch(e) {
//Will never get caught
}
Таким образом, вместо того, чтобы иметь первый аргумент обратного вызова, в значительной степени единственный разумный способ передавать ошибки асинхронно, кроме просто их выдачи.
Для этого потребуетсяв результате получается unhandled exception
, что в том виде, в каком оно звучит, подразумевает, что ничего не было сделано, чтобы вывести приложение из его запутанного состояния.
Исключения, почему они существуют
ЭтоОднако стоит отметить, что практически все части Node.js являются источниками событий, а создание исключения является событием низкого уровня, которое может быть обработано, как и все события:
//This won't immediately crash if connection fails
var socket = require("net").createConnection(5000);
socket.on("error", function(err) {
console.error("calm down...", err)
});
Это может-но-не следует доводить до крайности, чтобы перехватить все ошибки и создать приложение, которое будет очень стараться, чтобы никогда не вылетело.Это ужасная идея почти во всех случаях использования, поскольку она оставляет разработчика без представления о том, что происходит в состоянии приложения, и аналогична переносу main в try-catch.
Домены - группировка событийлогически
В рамках решения этой проблемы исключений, вызывающих сбой приложений, домены позволяют разработчику использовать, например, приложение Express.js, и пытаться разумно закрывать соединения всобытие катастрофического сбоя.
ES6
Вероятно, следует упомянуть, что это снова изменится, поскольку ES6 позволяет образцу генератора создавать асинхронные события, которые по-прежнему могут быть перехвачены с помощью блоков try / catch.
Коа (автор TJ Holowaychuck, тот же автор Express.js) заметно делает это.Он использует оператор ES6 yield
для создания блоков, которые, хотя и выглядят почти синхронно, обрабатываются обычным узлом асинхронно:
app.use(function *(next) {
try {
yield next;
}
catch (err) {
this.status = err.status || 500;
this.body = err.message;
this.app.emit('error', err, this);
}
});
app.use(function *(next) {
throw new Error('some error');
})
Этот пример был бесстыдно украден из здесь .