Wprowadzenie
Wyjątki i błędy z pewnością wystąpią, gdy użytkownicy będą wchodzić w interakcje z dowolną aplikacją, inżynierowie oprogramowania muszą wybrać sposób radzenia sobie z każdym błędem, który może się pojawić – świadomie lub nieświadomie. W rezultacie programiści zaplecza, którzy tworzą interfejsy API za pomocą Express, muszą pracować nad tym, aby tworzyć użyteczne, wydajne i użyteczne interfejsy API. Najważniejsze jest, aby radzić sobie z błędami w taki sposób, aby zbudować solidny system, ponieważ pomaga to skrócić czas programowania, bezpośrednie błędy, problemy z wydajnością i decyduje o sukcesie lub skalowalności rozwoju oprogramowania.
Czy musisz zarejestrować komunikat o błędzie, ukryć błąd, powiadomić użytkowników o błędzie lub napisać kod obsługujący błędy? Nie zastanawiaj się więcej.
W tym przewodniku dowiemy się, jak zbudować solidną bazę kodu obsługującą błędy dla aplikacji Express, która pomoże w wykrywaniu błędów aplikacji i podejmowaniu optymalnych działań w celu odzyskania dowolnej aplikacji z płynnej awarii w czasie wykonywania.
Uwaga: Będziemy używać Postmana do testowania interfejsu API w naszej wersji demonstracyjnej. Można go pobrać na Strona pobierania listonosza. Alternatywnie możesz po prostu użyć przeglądarki, wiersza poleceń curl
narzędzie lub jakiekolwiek inne narzędzie, które możesz znać.
Co to jest obsługa błędów?
W tworzeniu oprogramowania istnieją dwa różne rodzaje wyjątków: operacyjny i programowy.
- Awarie operacyjne mogą wystąpić w czasie wykonywania i aby zapobiec nagłemu zamknięciu aplikacji, musimy z wdziękiem obsługiwać te wyjątki za pomocą skutecznych metod obsługi błędów.
- Wyjątki programistyczne są zgłaszane ręcznie przez programistę, gdy wystąpi stan wyjątkowy.
Wyjątki operacyjne można traktować jako „nieoczekiwane, ale przewidziane” wyjątki (takie jak dostęp do indeksu poza granicami), a wyjątki programistyczne jako „oczekiwane i przewidywane” wyjątki (takie jak wyjątek formatowania liczb).
Obsługa wyjątków to procedura używana do znajdowania i naprawiania błędów w programie. Obsługa błędów wysyła komunikaty zawierające typ błędu, który wystąpił, oraz stos, w którym wystąpił błąd.
Uwaga: W informatyce wyjątki można odzyskać i zazwyczaj wynikają one z problemów operacyjnych lub programowych w czasie wykonywania. Błędy zwykle wynikają z czynników zewnętrznych, takich jak ograniczenia sprzętowe, problemy z łącznością, brak pamięci itp. W języku JavaScript terminy są często używane zamiennie, a niestandardowe wyjątki wynikają z Error
klasa. Plik Error
sama klasa reprezentuje zarówno błędy, jak i wyjątki.
W Expressie obsługa wyjątków odnosi się do sposobu, w jaki Express ustawia się do przechwytywania i przetwarzania synchronicznych i asynchronicznych wyjątków. Zaletą obsługi wyjątków w Expressie jest to, że jako programista nie musisz pisać własnych procedur obsługi wyjątków; Express jest dostarczany z domyślną obsługą wyjątków. Obsługa wyjątków pomaga w identyfikowaniu błędów i zgłaszaniu ich użytkownikowi. Zapewnia również różne strategie naprawcze i wdraża je w celu złagodzenia wyjątków.
Chociaż może się wydawać, że to wiele rzeczy, które są ukryte pod maską, obsługa wyjątków w Expressie nie spowalnia całego procesu programu ani nie wstrzymuje jego wykonywania.
Zrozumienie obsługi wyjątków w Express
Dzięki domyślnemu modułowi obsługi błędów, który jest dostarczany z Express, mamy do dyspozycji zestaw funkcji oprogramowania pośredniego, które pomagają automatycznie wychwytywać błędy w modułach obsługi tras. Wkrótce stworzymy projekt, który przełoży teorię na praktykę, jak zwracać poprawne błędy w aplikacji Express i jak nie wyciekać poufnych informacji.
Definiowanie funkcji oprogramowania pośredniczącego w Express
Funkcje oprogramowania pośredniczącego do obsługi błędów są zdefiniowane w taki sposób, że akceptują Error
obiekt jako pierwszy parametr wejściowy, po którym następują domyślne parametry dowolnej innej funkcji oprogramowania pośredniego: request
, response
, next
, next()
funkcja pomija całe bieżące oprogramowanie pośredniczące do następnej procedury obsługi błędów dla routera.
Konfigurowanie obsługi błędów w Express
Uruchom następujące polecenie w swoim terminalu, aby utworzyć aplikację Node i Express:
$ mkdir error-handling-express
W nowo utworzonym folderze zainicjujmy nowy projekt Node:
$ cd error-handling-express && npm init -y
To tworzy package.json
plik w naszym folderze.
Aby utworzyć serwer Express w naszej aplikacji Node, musimy zainstalować express
Pakiet, dotenv
do automatycznego ładowania zmiennych środowiskowych do .env
plik do process.env
przedmiot i nodemon
do ponownego uruchomienia aplikacji węzła, jeśli w katalogu zostanie zauważona zmiana pliku.
$ npm install express dotenv nodemon
Następnie utwórz plik app.js
plik w folderze projektu, który będzie służył jako plik indeksu dla aplikacji.
Teraz, gdy zainstalowaliśmy wszystkie potrzebne zależności dla naszej aplikacji Express, musimy skonfigurować skrypt do odczytu aplikacji w package.json
plik. Aby to osiągnąć, package.json
plik, aby scripts
obiekt jest jak pokazano poniżej:
"scripts": {
"start": "nodemon app.js"
},
Alternatywnie możesz pominąć używanie nodemon
, I użyć node app.js
zamiast.
Konfiguracja serwera Express
Aby skonfigurować serwer, musimy najpierw zaimportować do niego różne pakiety app.js
. Stworzymy również tzw .env
plik w katalogu projektu – do przechowywania wszystkich zmiennych środowiskowych dla aplikacji:
const express = require('express')
require('dotenv').config
PORT=4000
Zdefiniowaliśmy numer portu dla aplikacji w .env
, który jest ładowany i odczytywany przez dotenv
i można uzyskać do nich dostęp później.
Inicjowanie serwera Express Server
Teraz musimy zainicjować serwer Express i sprawić, by nasza aplikacja nasłuchiwała numeru portu aplikacji wraz z żądaniem trasy testowej – /test
. Zaktualizujmy app.js
pod instrukcjami importu:
const app = express();
const port = process.env.PORT || 4000;
app.get("/test", async (req, res) => {
return res.status(200).json({ success: true });
});
app.listen(port, () => {
console.log(`Server is running at port ${port}`);
});
Od tego momentu nauczymy się, jak radzić sobie z różnymi przypadkami błędów operacyjnych, które można napotkać w Expressie.
Obsługa błędów Nie znaleziono w Express
Załóżmy, że musisz pobrać wszystkich użytkowników z bazy danych użytkowników, możesz skutecznie obsłużyć scenariusz potencjalnego błędu, w którym w bazie danych nie ma żadnych danych, opakowując logikę w try/catch
block — mając nadzieję na wyłapanie jakiegokolwiek błędu, który mógłby wystąpić w catch
blok:
const getUser = () => undefined;
app.get("/get-user", async (req, res) => {
try {
const user = getUser();
if (!user) {
throw new Error('User not found');
}
} catch (error) {
console.log(error);
res.status(400).send(error.message)
}
return res.status(200).json({
success: true
});
});
To skutkuje:
User not found
Teraz, gdy to żądanie zostanie wysłane (możesz przetestować za pomocą Postmana) i żaden użytkownik nie istnieje w bazie danych, klient otrzymuje komunikat o błędzie „Nie znaleziono użytkownika”. Zauważysz również, że błąd jest również rejestrowany w konsoli.
Optymalizacja obsługi błędów za pomocą oprogramowania pośredniczącego obsługi błędów
Możemy zoptymalizować rozwój, tworząc oprogramowanie pośredniczące do obsługi błędów, które pojawiałoby się na końcu wszystkich zdefiniowanych tras, więc jeśli w jednej z tras zostanie zgłoszony błąd, Express automatycznie spojrzy na następne oprogramowanie pośrednie i będzie kontynuował listę dopóki nie dotrze do modułu obsługi błędów. Program obsługi błędów przetworzy błąd, a także odeśle odpowiedź do klienta.
Zapoznaj się z naszym praktycznym, praktycznym przewodnikiem dotyczącym nauki Git, zawierającym najlepsze praktyki, standardy przyjęte w branży i dołączoną ściągawkę. Zatrzymaj polecenia Google Git, a właściwie uczyć się to!
Aby rozpocząć, utwórz folder o nazwie middleware
w katalogu projektu iw tym folderze utwórz plik o nazwie errorHandler.js
który definiuje obsługę błędów:
const errorHandler = (error, req, res, next) => {
console.log(error);
res.status(400).send(error.message);
}
module.exports = errorHandler;
W naszej funkcji oprogramowania pośredniego uświadomiliśmy Expressowi, że nie jest to podstawowa funkcja oprogramowania pośredniego, ale obsługa błędów, dodając error
parametr przed 3 podstawowymi parametrami.
Teraz użyjemy obsługi błędów w naszym demo app.js
i obsłuż początkowy błąd pobierania użytkowników za pomocą oprogramowania pośredniczącego obsługi błędów, jak pokazano poniżej:
const getUser = () => undefined;
app.get("/get-user", async (req, res, next) => {
try {
const user = getUser();
if (!user) {
throw new Error("User not found");
}
} catch (error) {
return next(error);
}
});
app.use(errorHandler);
Możemy jeszcze bardziej zoptymalizować nasz kod, tworząc abstrakcję wokół pliku try/catch
logika. Możemy to osiągnąć tworząc nowy folder w katalogu projektu o nazwie utils
, a w nim utwórz plik o nazwie tryCatch.js
.
Abstrahować try-catch
logika – możemy zdefiniować funkcję, która przyjmuje inną funkcję (tzw kontroler) jako parametr i zwraca an async
funkcja, która będzie przechowywać a try/catch
dla dowolnego otrzymanego kontrolera.
Jeśli w sterowniku wystąpi błąd, zostanie on przechwycony w pliku catch
block, a następna funkcja nazywa się:
const tryCatch = (controller) => async (req, res, next) => {
try {
await controller(req, res);
} catch (error) {
return next(error);
}
};
module.exports = tryCatch;
Z try/catch
abstrakcji, możemy zrefaktoryzować nasz kod, aby był bardziej zwięzły, pomijając try-catch
klauzulę jawnie podczas pobierania użytkowników w app.js
:
const getUser = () => undefined;
app.get(
"/get-user",
tryCatch(async (req, res) => {
const user = getUser();
if (!user) {
throw new Error("User not found");
}
res.status(400).send(error.message);
})
);
Pomyślnie usunęliśmy logikę try-catch, a nasz kod nadal działa tak, jak wcześniej.
Obsługa błędów sprawdzania poprawności w Express
Na potrzeby tej demonstracji utworzymy nową trasę w naszej aplikacji Express do logowania — w celu zweryfikowania identyfikatora użytkownika podczas logowania. Najpierw zainstalujemy joi
package, aby pomóc w stworzeniu schematu, za pomocą którego możemy egzekwować wymagania:
$ npm i joi
Następnie utwórz schemat, który jest a Joi.object
z userId
który musi być liczbą i jest wymagany – co oznacza, że żądanie musi pasować do obiektu z identyfikatorem użytkownika.
Możemy użyć validate()
metoda w obiekcie schematu, aby sprawdzić poprawność każdego wejścia względem schematu:
const schema = Joi.object({
userId: Joi.number().required(),
});
app.post(
"/login",
tryCatch(async (req, res) => {
const {error, value} = schema.validate({});
if (error) throw error;
})
);
Jeśli pusty obiekt zostanie przekazany do validate()
metoda, błąd zostałby poprawnie obsłużony, a komunikat o błędzie zostałby wysłany do klienta:
Na konsoli otrzymujemy również dostęp do m.in details
tablica zawierająca różne szczegóły dotyczące błędu, które w razie potrzeby można przekazać użytkownikowi.
Aby konkretnie obsłużyć błędy sprawdzania poprawności w taki sposób, aby przekazać odpowiednie szczegóły błędu dla każdego błędu sprawdzania poprawności, oprogramowanie pośredniczące obsługi błędów można poddać refaktoryzacji:
const errorHandler = (error, req, res, next) => {
console.log(error);
if (error.name === "ValidationError") {
return res.status(400).send({
type: "ValidationError",
details: error.details,
});
}
res.status(400).send(error.message);
};
module.exports = errorHandler;
Z errorHandler.js
teraz dostosowane, gdy wysyłamy to samo żądanie z pustym obiektem przekazanym do validate()
metoda:
Mamy teraz dostęp do dostosowanego obiektu, który zwraca komunikaty w bardziej czytelny/przyjazny sposób. W ten sposób jesteśmy w stanie wysyłać i obsługiwać różne rodzaje błędów w zależności od rodzaju przychodzącego błędu.
Wnioski
W tym przewodniku omówiliśmy każdy aspekt obsługi błędów w Express.js, w tym sposób domyślnej obsługi kodu synchronicznego i asynchronicznego, tworzenie własnych klas błędów, pisanie niestandardowych funkcji oprogramowania pośredniego obsługujących błędy oraz dostarczanie next
jako osoba zajmująca się końcowym połowem
Jak w przypadku każdego zadania, istnieją również najlepsze praktyki podczas opracowywania, które obejmują efektywną obsługę błędów, a dzisiaj nauczyliśmy się, jak solidnie obsługiwać błędy w aplikacji Express.
Właściwa obsługa błędów oznacza nie tylko skrócenie czasu opracowywania dzięki łatwemu znajdowaniu błędów, ale także tworzenie solidnej bazy kodu dla aplikacji na dużą skalę. W tym przewodniku widzieliśmy, jak skonfigurować oprogramowanie pośredniczące do obsługi błędów operacyjnych. Niektóre inne sposoby poprawy obsługi błędów obejmują: nie wysyłanie śladów stosu, płynne zatrzymywanie procesów w celu obsługi nieprzechwyconych wyjątków, dostarczanie odpowiednich komunikatów o błędach, wysyłanie dzienników błędów i konfigurowanie klasy rozszerzającej Error
class.
Mam nadzieję, że przykłady, których użyłem w tym samouczku, były dla Ciebie przyjemne. Omówiłem różne scenariusze, z którymi można się potencjalnie spotkać podczas pisania aplikacji Express do użytku w świecie rzeczywistym w zakresie zarządzania błędami. Proszę, daj mi znać, jeśli jest coś, co przegapiłem. Przyniesie to korzyści nam i pomoże mi dowiedzieć się więcej. Miłego dnia i dzięki za przeczytanie.
Możesz odwołać się do całego kodu źródłowego użytego w artykule na temat Github.