Diese Seite übersetzen

Fehler beim Umgang

Error Handling bezieht sich darauf, wie Express Fehler fängt und verarbeitet, die sowohl synchron als auch asynchron auftritt. Express kommt mit einem Standardfehler -Handler, damit Sie nicht Ihren eigenen schreiben müssen, um loszulegen.

Fehler beim Fangen

Es ist wichtig sicherzustellen, dass Express alle Fehler, die auftreten, während Routen-Handler und Middleware ausführt.

Fehler, die im synchronen Code innerhalb von Routenhandlern und Middleware auftreten, erfordern keine zusätzliche Arbeit. If synchronous code throws an error, then Express will catch and process it. Zum Beispiel:

app.get('/', (req, res) => {
throw new Error('BROKEN'); // Express will catch this on its own.
});

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where Express will catch and process them. Zum Beispiel:

app.get('/', (req, res, next) => {
fs.readFile('/file-does-not-exist', (err, data) => {
if (err) {
next(err); // Pass errors to Express.
} else {
res.send(data);
}
});
});

Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error. Zum Beispiel:

app.get('/user/:id', async (req, res, next) => {
const user = await getUserById(req.params.id);
res.send(user);
});

Wenn getUserById einen Fehler oder eine Ablehnung, wird next entweder mit dem Wurffehler oder dem abgelehnten Wert aufgerufen. Wenn kein abgelehnter Wert angegeben wird, wird next mit einem Standard-Fehlerobjekt aufgerufen, das vom Express-Router bereitgestellt wird.

Wenn du etwas an die next() Funktion übergibt (außer den String 'route'), Express betrachtet die aktuelle Anfrage als Fehler und überspringt alle verbleibenden Funktionen zur Fehlerbehandlung und Middleware.

Wenn der Rückruf in einer Sequenz keine Daten enthält, nur Fehler, kannst du den Code wie folgt vereinfachen:

app.get('/', [
function (req, res, next) {
fs.writeFile('/inaccessible-path', 'data', next);
},
function (req, res) {
res.send('OK');
},
]);

Im obigen Beispiel wird next als Callback für fs.writeFile bereitgestellt, , das mit oder ohne Fehler aufgerufen wird. Wenn kein Fehler vorliegt, wird der zweite -Handler ausgeführt, sonst fängt und verarbeitet Express den Fehler.

Sie müssen Fehler, die im asynchronen Code auftreten, der von Routenhandlern oder Middleware aufgerufen wird, auffangen und an Express zur Verarbeitung weiterleiten. Zum Beispiel:

app.get('/', (req, res, next) => {
setTimeout(() => {
try {
throw new Error('BROKEN');
} catch (err) {
next(err);
}
}, 100);
});

Das obige Beispiel benutzt einen “try…catch”-Baustein, um Fehler im asynchronen Code zu fangen und sie an den Express zu übergeben. Wenn der Block try...catch weggelassen wurde, würde Express den Fehler nicht auffinden, da er nicht Teil des synchronen Handlercodes ist.

Verwende Versprechungen, um den Overhead des try...catch-Bausteins zu vermeiden oder wenn du Funktionen benutzt, die Versprechen zurückgeben. Zum Beispiel:

app.get('/', (req, res, next) => {
Promise.resolve()
.then(() => {
throw new Error('BROKEN');
})
.catch(next); // Errors will be passed to Express.
});

Da Versprechungen automatisch sowohl synchrone Fehler als auch abgelehnte Versprechungen fangen, du kannst einfach next angeben, da der letzte Catch Handler und Express Fehler fängt an weil der Catch-Handler den Fehler als erstes Argument angibt.

Sie können auch eine Kette von Handlern verwenden, um sich auf synchrone Fehler zu stützen, indem Sie den asynchronen Code auf etwas Triviales reduzieren. Zum Beispiel:

app.get('/', [
function (req, res, next) {
fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
res.locals.data = data;
next(err);
});
},
function (req, res) {
res.locals.data = res.locals.data.split(',')[1];
res.send(res.locals.data);
},
]);

Das obige Beispiel hat ein paar triviale Anweisungen aus dem Aufruf readFile . If readFile causes an error, then it passes the error to Express, otherwise you quickly return to the world of synchronous error handling in the next handler in the chain. Dann versucht das obige Beispiel die Daten zu verarbeiten. Wenn dies fehlschlägt, fängt der Synchron-Fehlerhandler ihn ab. Hätten Sie diese Verarbeitung innerhalb von mit dem readFile Callback durchgeführt, dann könnte sich die Anwendung beenden und die Express-Fehler Handler würden nicht laufen.

Welche Methode Sie auch immer verwenden, wenn Sie wollen, dass Express-Fehlerbehandler aufgerufen werden und die -Anwendung überleben soll, Sie müssen sicherstellen, dass Express den Fehler empfängt.

Der Standard-Fehlerhandler

Express kommt mit einem integrierten Fehlerbehandler, der sich um Fehler kümmert, die in der App auftreten könnten. Diese Standard-Middleware-Funktion wird am Ende des Middleware-Funktionstacks hinzugefügt.

Wenn du einen Fehler an next() übergibt und ihn nicht in einem benutzerdefinierten Handler behandelst, es wird vom eingebauten Fehlerhandler behandelt; wird der Fehler mit der Stack-Spur an den Client geschrieben. The stack trace is not included in the production environment.

Note

Setze die Umgebungsvariable NODE_ENV auf production, um die App im Produktionsmodus auszuführen.

Wenn ein Fehler geschrieben wird, werden folgende Informationen zur Antwort hinzugefügt:

  • Der res.statusCode wurde von err.status (oder err.statusCode) gesetzt. Wenn sich dieser Wert außerhalb des 4xx oder 5xx Bereichs befindet, wird er auf 500 gesetzt.
  • Die res.statusMessage wurde gemäß dem Statuscode gesetzt.
  • Der Körper wird der HTML-Code der Statuscode-Nachricht sein, wenn in der Produktion -Umgebung, andernfalls ‘err.stack’ ist.
  • Alle in einem err.headers Objekt angegebenen Header.

Wenn du next() mit einem Fehler aufruft, nachdem du die Antwort geschrieben hast (z. B. wenn beim Streamen der Antwort auf den Client ein Fehler aufgetreten ist), der Express-Standardfehlerhandler schließt die Verbindung und schlägt die Anfrage fehl.

Wenn Sie also eine benutzerdefinierte Fehlerbehandlung hinzufügen, müssen Sie den Standard-Express-Fehlerbehandler an delegieren wenn die Kopfzeilen bereits an den Client gesendet wurden:

function errorHandler(err, req, res, next) {
if (res.headersSent) {
return next(err);
}
res.status(500);
res.render('error', { error: err });
}

Beachte, dass der Standard-Fehlerhandler ausgelöst werden kann, wenn du next() mit einem Fehler in deinem Code mehrmals aufrufst, auch wenn benutzerdefinierte Fehler beim Umgang mit Middleware vorhanden sind.

Andere Fehler beim Umgang mit Middleware finden Sie unter Express Middleware.

Schreibfehler

Definieren Sie die Middleware-Funktionen wie andere Middleware-Funktionen außer Funktionen zur Fehlerbehandlung haben vier Argumente anstelle von drei: (err, req, res, next). Zum Beispiel:

app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});

Du definierst die Middleware zuletzt nach anderen app.use() und Routet Anrufe; zum Beispiel:

const bodyParser = require('body-parser');
const methodOverride = require('method-override');
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use((err, req, res, next) => {
// logic
});

Antworten innerhalb einer Middleware-Funktion können in jedem Format sein, wie z.B. in einer HTML-Fehlerseite, einer einfachen Nachricht oder einem JSON-String.

Für organisatorische (und höherstufige Framework) Zwecke können Sie verschiedene Middleware-Funktionen definieren, so wie Sie es mit den regulären Middleware-Funktionen würden. Zum Beispiel, um einen Fehlerhandler für Anfragen mit XHR und denen ohne folgende zu definieren:

const bodyParser = require('body-parser');
const methodOverride = require('method-override');
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.use(bodyParser.json());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

In diesem Beispiel könnten die generischen logErrors Anfrage und Fehlerinformationen in stderr schreiben, zum Beispiel:

function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}

Auch in diesem Beispiel wird clientErrorHandler wie folgt definiert; in diesem Fall wird der Fehler explizit an den nächsten weitergegeben.

Beachten Sie, dass, wenn not in einer Fehlerbehandlungsfunktion “Weiter” aufruft, Sie dafür verantwortlich sind, die Antwort zu schreiben (und zu beenden). Andernfalls werden diese Anträge “hängen” und sind nicht für die Müllsammlung berechtigt.

function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' });
} else {
next(err);
}
}

Implementierung der “catch-all” errorHandler Funktion wie folgt (zum Beispiel):

function errorHandler(err, req, res, next) {
res.status(500);
res.render('error', { error: err });
}

Wenn du einen Route-Handler mit mehreren Callback-Funktionen hast, kannst du den Parameter route verwenden, um zum nächsten Route-Handler zu springen. Zum Beispiel:

app.get(
'/a_route_behind_paywall',
(req, res, next) => {
if (!req.user.hasPaid) {
// continue handling this request
next('route');
} else {
next();
}
},
(req, res, next) => {
PaidContent.find((err, doc) => {
if (err) return next(err);
res.json(doc);
});
}
);

In diesem Beispiel wird der getPaidContent Handler übersprungen, aber alle verbleibenden Handler in app für /a_route_behind_paywall würden weiterhin ausgeführt werden.

Note

Aufrufe in next() und next(err) zeigen an, dass der aktuelle Handler abgeschlossen ist und in welchem Zustand ist. next(err) überspringt alle verbleibenden Handler in der Kette mit Ausnahme derjenigen, die bis zu eingerichtet sind, um Fehler wie oben beschrieben zu handhaben.