Чому перший параметр?
Через асинхронну природу Node.js, шаблон першого параметра як помилка став добре утвердженим як умова для обробки помилок Node.js userland . Це тому, що асинхронний:
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)
});
Це можна, але не слід сприймати до крайності, щоб зрозуміти всі помилки та зробити програму, яка дуже намагатиметься ніколи не виходити з ладу . Це жахлива ідея майже в кожному випадку використання, оскільки вона не залишить розробника без уявлення про те, що відбувається в стані програми, і є аналогом обгортці основного в try-catch.
Домени - групування подій логічно
У рамках вирішення цієї проблеми винятків, завдяки яким програми перепадають, домени дозволяють розробнику взяти, наприклад, програму Express.js, і спробувати розумно відключити з'єднання у випадку катастрофічного збою.
ES6
Це, мабуть, згадує, що це знову зміниться, оскільки ES6 дозволяє схемі генератора створювати асинхронні події, які все ще підлягають пошуку за допомогою блоків спробу / лову.
Коа (написано Т. Дж. Головайчуком, тим самим оригінальним автором Express.js) помітно це робить. Він використовує yield
оператор ES6 для створення блоків, які, хоча і виглядають майже синхронними, обробляються у звичайному асинхронному вузлі:
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');
})
Цей приклад був безсоромно викрадений звідси .