Als ich anfing, mit Express zu arbeiten und herauszufinden, wie ich mit Fehlern umgehen sollte, hatte ich es schwer. Es gab das Gefühl, dass niemand darüber schrieb, was ich brauchte. Infolgedessen musste ich selbst nach Antworten auf meine Fragen suchen. Heute möchte ich alles erzählen, was ich über die Fehlerbehandlung in Express-Anwendungen weiß. Beginnen wir mit synchronen Fehlern.

Synchrone Fehlerbehandlung
Wenn Sie einen synchronen Fehler behandeln müssen, können Sie
throw
mithilfe der
throw
Anweisung
throw
solchen Fehler im Express-Request-Handler auslösen. Bitte beachten Sie, dass Request-Handler auch als "Controller" bezeichnet werden. Ich bevorzuge jedoch die Verwendung des Begriffs "Request-Handler", da mir dies klarer erscheint.
So sieht es aus:
app.post('/testing', (req, res) => { throw new Error('Something broke! ') })
Solche Fehler können mit dem Express Error Handler abgefangen werden. Wenn Sie keinen eigenen Fehlerbehandler geschrieben haben (wir werden weiter unten darauf eingehen), behandelt Express den Fehler mit dem Standardhandler.
Die Standard-Express-Fehlerbehandlungsroutine führt folgende Aktionen aus:
- Legt den HTTP-Antwortstatuscode auf 500 fest.
- Sendet eine Textantwort an die Entität, die die Anforderung ausführt.
- Protokolliert eine Textantwort an die Konsole.
Fehlermeldung in der Konsole angezeigtAsynchrone Fehlerbehandlung
Um asynchrone Fehler zu behandeln, müssen Sie über das
next
Argument einen Fehler an den Express-Fehlerbehandler senden:
app.post('/testing', async (req, res, next) => { return next(new Error('Something broke again! ')) })
Dies ist, was auf die Konsole gelangt, wenn dieser Fehler protokolliert wird.
Fehlermeldung in der Konsole angezeigtWenn Sie das Konstrukt async / await in einer Express-Anwendung verwenden, müssen Sie eine Wrapper-Funktion wie
express-async-handler verwenden . Auf diese Weise können Sie asynchronen Code ohne
Try / Catch- Blöcke schreiben. Weitere Informationen zu async / await in Express finden Sie
hier .
const asyncHandler = require('express-async-handler') app.post('/testing', asyncHandler(async (req, res, next) => {
Nachdem der Anforderungshandler in den
express-async-handler
, können Sie wie oben beschrieben mit der
throw
Anweisung einen Fehler
throw
. Dieser Fehler wird an den Express-Fehlerbehandler weitergeleitet.
app.post('/testing', asyncHandler(async (req, res, next) => { throw new Error('Something broke yet again! ') }))
Fehlermeldung in der Konsole angezeigtSchreiben Sie Ihren eigenen Fehlerbehandler
Express-Fehlerbehandlungsroutinen verwenden vier Argumente:
- Fehler
- req
- res
- als nächstes
Sie müssen nach Zwischenhandlern und Routen platziert werden.
app.use() app.get() app.post() app.put() app.delete()
Wenn Sie eine eigene Fehlerbehandlungsroutine erstellen, verwendet Express die Standard-Fehlerbehandlungsroutine nicht mehr. Um den Fehler zu behandeln, müssen Sie eine Antwort für die Front-End-Anwendung generieren, die den Endpunkt adressiert hat, an dem der Fehler aufgetreten ist. Dies bedeutet, dass Sie Folgendes tun müssen:
- Generieren und senden Sie einen geeigneten Antwortstatuscode.
- Bilden und senden Sie eine passende Antwort.
Welcher Statuscode im Einzelfall angemessen ist, hängt davon ab, was genau passiert ist. Hier ist eine Liste der häufigsten Fehler, auf die Sie vorbereitet sein sollten:
- Fehler
400 Bad Request
Fehlerhafte 400 Bad Request
. Wird in zwei Situationen verwendet. Erstens, wenn der Benutzer das erforderliche Feld nicht in die Anforderung aufgenommen hat (z. B. wurde das Feld mit den Kreditkarteninformationen in dem gesendeten Zahlungsformular nicht ausgefüllt). Zweitens, wenn die Anfrage falsche Daten enthält (z. B. unterschiedliche Passwörter in das Passwortfeld und in das Passwortbestätigungsfeld eingeben). - Fehler
401 Unauthorized
. Dieser Antwortstatuscode wird angewendet, wenn der Benutzer falsche Anmeldeinformationen eingegeben hat (z. B. Benutzername, E-Mail-Adresse oder Kennwort). - Fehler
403 Forbidden
. Wird verwendet, wenn der Benutzer keinen Zugriff auf den Endpunkt hat. - Fehler
404 Not Found
. Es wird in Fällen verwendet, in denen der Endpunkt nicht erkannt werden kann. - Fehler
500 Internal Server Error
. Es wird angewendet, wenn die vom Front-End gesendete Anforderung korrekt generiert wurde, im Back-End jedoch ein Fehler aufgetreten ist.
Nachdem der entsprechende Antwortstatuscode definiert wurde, muss er mit
res.status
:
app.use((error, req, res, next) => {
Der Antwortstatuscode sollte der Fehlermeldung entsprechen. Senden Sie dazu den Statuscode zusammen mit dem Fehler.
Am einfachsten geht das mit dem
http-errors- Paket. Es können drei fehlerhafte Informationen gesendet werden:
- Der Antwortstatuscode.
- Die mit dem Fehler verknüpfte Nachricht.
- Alle Daten, die gesendet werden müssen (dies ist optional).
So installieren Sie das
http-errors
:
npm install http-errors --save
So verwenden Sie dieses Paket:
const createError = require('http-errors')
Betrachten Sie ein Beispiel, mit dem Sie dies alles richtig verstehen können.
Stellen Sie sich vor, wir versuchen, einen Benutzer unter seiner E-Mail-Adresse zu finden. Dieser Benutzer kann jedoch nicht gefunden werden. Infolgedessen entscheiden wir uns, als Antwort auf die entsprechende Anforderung einen Fehler "
User not found
zu senden, um den Anrufer zu informieren, dass der Benutzer nicht gefunden wurde.
Folgendes müssen wir tun, um den Fehler zu erstellen:
- Setzen Sie den Antwortstatuscode auf
400 Bad Request
(schließlich hat der Benutzer falsche Daten eingegeben). Dies wird unser erster Parameter sein. - Senden Sie eine Nachricht an den Anrufer wie
User not found
. Dies wird der zweite Parameter sein.
app.put('/testing', asyncHandler(async (req, res) => { const { email } = req.body const user = await User.findOne({ email })
Sie können den Statuscode mit dem Konstrukt
error.status
und die Fehlermeldung mit
error.message
:
Das Ergebnis von Protokollierungsfehlern in der KonsoleAnschließend wird der Antwortstatus mit
res.status
und die Nachricht in
res.json
:
app.use((error, req, res, next) => {
Persönlich bevorzuge ich das Senden eines Statuscodes, einer Nachricht und eines Stack-Trace-Ergebnisses für solche Antworten. Dies erleichtert das Debuggen.
app.use((error, req, res, next) => {
▍ Standardantwortstatuscode
Wenn die Fehlerquelle nicht
createError
, verfügt sie nicht über die Eigenschaft
status
. Hier ist ein Beispiel, in dem versucht wurde, eine nicht vorhandene Datei mit
fs.readFile
zu lesen:
const fs = require('fs') const util = require('util')
Ein solches Fehlerobjekt hat nicht die Eigenschaft
status
:
app.use((error, req, res, next) => { console.log('Error status: ', error.status) console.log('Message: ', error.message) })
Das Ergebnis von Protokollierungsfehlern in der KonsoleIn solchen Fällen können Sie den Standardfehlercode festlegen. Wir sprechen nämlich über den
500 Internal Server Error
:
app.use((error, req, res, next) => { res.status(error.status || 500) res.json({ status: error.status, message: error.message, stack: error.stack }) })
▍Ändern des Fehlerstatuscodes
Angenommen, wir lesen eine bestimmte Datei anhand der vom Benutzer bereitgestellten Daten. Wenn eine solche Datei nicht existiert, müssen wir einen
400 Bad Request
Fehler
400 Bad Request
. Immerhin kann der Server nicht gefunden werden, da die Datei nicht gefunden werden kann.
In diesem Fall müssen Sie das try / catch-Konstrukt verwenden, um den ursprünglichen Fehler abzufangen. Dann müssen Sie das
createError
mit
createError
neu
createError
:
app.get('/testing', asyncHandler(async (req, res, next) => { try { const { file } = req.body const contents = await readFilePromise(path.join(__dirname, file)) } catch (error) { throw createError(400, `File ${file} does not exist`) } })
▍ 404 Fehlerbehandlung
Wenn die Anforderung alle Intermediate-Handler und -Routen durchlaufen hat, aber nicht verarbeitet wurde, bedeutet dies, dass der einer solchen Anforderung entsprechende Endpunkt nicht gefunden wurde.
Um
404 Not Found
Fehler zu behandeln, müssen Sie zwischen den Routen und der Fehlerbehandlungsroutine eine zusätzliche Behandlungsroutine hinzufügen. So sieht die Erstellung des 404-Fehlerobjekts aus:
Fehlerdetails▍ ERR_HTTP_HEADERS_SENT Fehlerhinweise
Keine Panik, wenn die Fehlermeldung
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
. Es entsteht, weil im selben Handler die Methode, die die Antwortheader setzt, wiederholt aufgerufen wird. Mit den folgenden Methoden werden die Antwortheader automatisch festgelegt:
- res.send
- res.json
- res.render
- res.sendFile
- res.sendStatus
- res.end
- res.redirect
Wenn Sie
res.json
res.render
und
res.json
im selben
res.render
res.json
, wird der Fehler
ERR_HTTP_HEADERS_SENT
:
app.get('/testing', (req, res) => { res.render('new-page') res.json({ message: '¯\_(ツ)_/¯' }) })
Wenn dieser Fehler auftritt, überprüfen Sie den Code des Antworthandlers sorgfältig und stellen Sie sicher, dass es keine Situationen gibt, in denen mehrere der oben beschriebenen Methoden aufgerufen werden.
▍ Fehlerbehandlung und Datenstreaming
Wenn beim Streamen der Antwort auf das Frontend ein Fehler
ERR_HTTP_HEADERS_SENT
, tritt möglicherweise derselbe
ERR_HTTP_HEADERS_SENT
Fehler auf.
In diesem Fall muss die Fehlerbehandlung an Standardhandler übergeben werden. Ein solcher Handler sendet einen Fehler und beendet die Verbindung automatisch.
app.use((error, req, res, next) => {
Zusammenfassung
Heute habe ich Ihnen alles gesagt, was ich über die Fehlerbehandlung in Express weiß. Ich hoffe, dies hilft Ihnen beim Schreiben zuverlässigerer Express-Anwendungen.
Sehr geehrte Leser! Wie gehen Sie mit Fehlern in Ihren Node.js-Projekten um?
