Warum erster Parameter?
Aufgrund der asynchronen Natur von Node.js hat sich das Muster des ersten Parameters als Fehler als Konvention für die Fehlerbehandlung von Node.js im Benutzerland gut etabliert . Dies liegt daran, dass asynchron:
try {
setTimeout(function() {
throw 'something broke' //Some random error
}, 5)
}
catch(e) {
//Will never get caught
}
Stattdessen ist das erste Argument des Rückrufs so ziemlich die einzig sinnvolle Möglichkeit, Fehler asynchron zu übergeben, anstatt sie nur zu werfen.
Dies führt zu einem Ergebnis unhandled exception
, das genau so klingt, wie es sich anhört, dass nichts unternommen wurde, um die Anwendung aus ihrem verwirrten Zustand zu bringen.
Ausnahmen, warum gibt es sie?
Es ist jedoch erwähnenswert, dass praktisch alle Teile von Node.js Ereignisemitter sind und das Auslösen einer Ausnahme ein Ereignis auf niedriger Ebene ist, das wie alle Ereignisse behandelt werden kann:
//This won't immediately crash if connection fails
var socket = require("net").createConnection(5000);
socket.on("error", function(err) {
console.error("calm down...", err)
});
Dies kann, sollte aber nicht auf die Spitze getrieben werden, um alle Fehler abzufangen und eine Anwendung zu erstellen, die sich sehr bemüht, niemals abzustürzen. Dies ist in fast jedem Anwendungsfall eine schreckliche Idee, da der Entwickler keine Ahnung davon hat, was im Anwendungsstatus vor sich geht, und analog dazu ist, main in try-catch zu verpacken.
Domänen - Ereignisse logisch gruppieren
Im Rahmen der Bewältigung dieses Problems von Ausnahmen, bei denen Anwendungen umfallen, können Entwickler mithilfe von Domänen beispielsweise die Anwendung Express.js verwenden und versuchen, Verbindungen im Falle eines katastrophalen Ausfalls sinnvoll zu schließen.
ES6
Es wird wahrscheinlich erwähnt, dass sich dies erneut ändern wird, da ES6 es dem Generatormuster ermöglicht, asynchrone Ereignisse zu erstellen, die mit try / catch-Blöcken noch abfangbar sind.
Koa (geschrieben von TJ Holowaychuck, dem gleichen Originalautor von Express.js) tut dies merklich. Mit der ES6- yield
Anweisung werden Blöcke erstellt, die zwar nahezu synchron erscheinen, jedoch auf die übliche asynchrone Weise des Knotens behandelt werden:
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');
})
Dieses Beispiel wurde von hier aus schamlos gestohlen .