Vezérlőpult
8. Hibakezelés · Express alapok

Express alapok · 8. tananyag

Hibakezelés

Eddig minden végpontban külön írtuk le, mi történjen hiba esetén. Ez a fejezet egyetlen helyre vonja össze — és tisztázza azt a kérdést is, amit a 3. fejezetben félbehagytunk: az Express 5 tényleg elkapja az aszinkron hibákat, de pontosan mit, és mit nem.

3 tanóraKözponti hibakezelőAszinkron hibák

A fejezet végén tudni fogod

1Mi számít hibának?

Nem minden hiba egyforma. A különbségtétel dönti el, mit csinálunk vele:

Működési hibaProgramozói hiba
Mi ez?Számítottunk rá, csak nem történt megA kódunk hibás
PéldaNincs ilyen termék · hibás JSON · nincs jogosultságundefined mező olvasása · elgépelt függvénynév
Kinek szól?A kliensnek — meg tudja oldaniA fejlesztőnek — javítani kell
Státuszkód4xx5xx
Mit mutatunk?Pontos, hasznos üzenetetSemmit — csak annyit, hogy hiba történt
NaplózásElég rövidenTeljes veremkiírással
A SZABÁLY EGY MONDATBAN

A 4xx azt jelenti: „te hibáztál, és meg tudod javítani”. Az 5xx azt: „mi hibáztunk, te nem tehetsz semmit”. Ha a kliens a hibaüzenetből nem tud továbblépni, akkor rossz kódot adtál neki.

Milyen státuszkód jár?

Hat helyzet a webshop API-ból. Válaszd ki a megfelelő státuszkódot — a 4xx/5xx döntés a lényeg.

1 / 6Helyes: 0
…

2A 404-kezelő

Ha egyetlen útvonal sem illeszkedik, a lánc végére ér a kérés. Ott várja a 404-kezelő:

// src/middlewares/nem-talalhato.js
export function nemTalalhato(req, res) {
  res.status(404).json({
    error: {
      message: `Nincs ilyen végpont: ${req.method} ${req.originalUrl}`,
      code: "NINCS_VEGPONT"
    }
  });
}

Az eredmény:

GET /nincs   →   404   {"error":{"message":"Nincs ilyen végpont: GET /nincs","code":"NINCS_VEGPONT"}}

A helye: minden útvonal után, a hibakezelő előtt

✓ HELYES SORREND app.use("/api/products", router) app.use(nemTalalhato) app.use(hibakezelo) ✗ HIBAKEZELŐ ELÖL app.use(hibakezelo) app.use("/api/…", router) Tünet: soha nem fut le, az Express HTML-hibaoldala megy vissza. ✗ 404 A VÉGÉN app.use(hibakezelo) app.use(nemTalalhato) Tünet: a hibák is a 404-kezelőhöz futnak be — rossz kóddal. MIÉRT PONT EBBEN A SORRENDBEN? A 404 azt jelenti: „idáig eljutott, de egyik útvonal sem illeszkedett”. A hibakezelő pedig azt: „valahol az egész láncban baj történt”. A tágabb eset kerül hátrébb.
1. ábra — A lánc vége. Mindkét rossz sorrendet kipróbáltuk.
MIÉRT NEM MINTÁVAL?

Mert az app.get("*") Express 5-ben hibát dob (3. fejezet). A minta nélküli app.use(fv) minden kérésre illeszkedik — pontosan ezt akarjuk a lánc végén.

MIÉRT NEM DOB HIBÁT?

Mert a „nincs ilyen végpont” működési hiba: a kliens elgépelte az URL-t. Nem kell hozzá a hibakezelő gépezete — elég egy egyszerű válasz. (Van, aki next(new HttpHiba(404, …)) alakban a hibakezelőnek adja át; mindkét megoldás elfogadott, mi az egyszerűbbet választjuk.)

Ha nincs 404-kezelőd

Az Express beépítettje válaszol — HTML-lel:

404   text/html   <!DOCTYPE html> … <pre>Cannot GET /nincs</pre>

Egy JSON API-nál ez rossz: a kliens JSON.parse hibára fut, és nem tudja meg, mi történt.

3A központi hibakezelő

Négy paraméter, a lánc legvégén — a 6. fejezetből már ismerős:

// src/middlewares/hibakezelo.js
export function hibakezelo(err, req, res, next) {
  // 1) naplózás — mindig, mielőtt bármi mást tennénk
  console.error(`[HIBA] ${req.method} ${req.originalUrl}`, err);

  // 2) ha a válasz már elment, nincs mit tenni
  if (res.headersSent) {
    return next(err);
  }

  // 3) válasz a kliensnek
  const statusz = err.status ?? 500;

  res.status(statusz).json({
    error: {
      message: statusz < 500 ? err.message : "Váratlan szerverhiba történt.",
      code: statusz < 500 ? (err.code ?? "SZERVERHIBA") : "SZERVERHIBA"
    }
  });
}
LépésMiért?
1. NaplózásEz az egyetlen hely, ahol minden hiba átmegy — itt éri meg naplózni
2. res.headersSentHa a válasz már elment, a res.status() hívás újabb hibát okozna. Ilyenkor az Express beépített kezelőjének adjuk át, ami lezárja a kapcsolatot
3. err.status ?? 500Ha a hiba tudja, milyen kódot érdemel, azt használjuk; ha nem, 500
A < 500 feltétel4xx-nél a hiba saját üzenete és kódja megy ki, 5xx-nél általános szöveg és SZERVERHIBA — a részletek csak a naplóba kerülnek. A kódot is le kell cserélni: a Node saját hibáinak is van kódja (kipróbálva: hiányzó fájlnál ENOENT), és az a belső működésről árulkodik
MIÉRT ?? ÉS NEM ||?

Mert az err.status || 500 a 0 értéket is lecserélné — igaz, hogy 0-s státuszkód nincs, de a ?? fejezi ki pontosan a szándékot: „csak akkor, ha nincs megadva”. Ugyanaz a különbség, mint a 4. fejezetben a query paramétereknél.

Amit a hibakezelő elkap

Mind a négy módon érkező hiba ideér — az eredmények:

Ahogy a hiba keletkezikPéldaEredmény
throw szinkron kezelőbenapp.get("/x", () => { throw new Error(…) })500
throw async kezelőbenapp.get("/x", async () => { throw new Error(…) })500
throw async middleware-benapp.use(async (q, s, n) => { throw new Error(…) })500
next(hiba)app.get("/x", (q, s, n) => n(new Error(…)))500

A harmadik sor az Express 5 újdonsága — a 4-esben ez a hiba elveszett volna.

4Saját hibaosztály

Ahhoz, hogy a hibakezelő tudja, milyen státuszkód és hibakód jár, a hibának magával kell hoznia ezt az információt:

// src/utils/HttpHiba.js
export class HttpHiba extends Error {
  constructor(status, message, code) {
    super(message);
    this.name = "HttpHiba";
    this.status = status;
    this.code = code;
  }
}
ElemMit csinál?
extends ErrorÖrökli a message mezőt és a veremkiírást (stack)
super(message)Átadja az üzenetet az Error konstruktorának — enélkül üres lenne
this.nameEz jelenik meg a naplóban a hiba neveként
this.statusA státuszkód, amit a hibakezelő kiolvas
this.codeAz állandó, gépnek szóló kód (5. fejezet)

A throw előnye a return res.…-szel szemben

Eddig — return res.status(…)A RETURN FELEJTHETŐ
app.get("/api/products/:id", (req, res) => {
  const id = Number(req.params.id);

  if (Number.isNaN(id)) {
    return res.status(400).json({
      error: { message: "…", code: "…" }
    });
  }

  const termek = keres(id);
  if (!termek) {
    return res.status(404).json({
      error: { message: "…", code: "…" }
    });
  }

  res.json(termek);
});
Mostantól — throw new HttpHiba(…)RÖVIDEBB
app.get("/api/products/:id", (req, res) => {
  const id = Number(req.params.id);

  if (Number.isNaN(id)) {
    throw new HttpHiba(400,
      "Az azonosító csak szám lehet.", "ERVENYTELEN_ID");
  }

  const termek = keres(id);
  if (!termek) {
    throw new HttpHiba(404,
      "Nincs ilyen termék.", "TERMEK_NEM_TALALHATO");
  }

  res.json(termek);
});

Az eredmény:

GET /sajat   →   404   {"nev":"HttpHiba","uzenet":"Nincs ilyen termék.","kod":"TERMEK_NEM_TALALHATO"}
A throw AZONNAL MEGSZAKÍTJA A FÜGGVÉNYT

A return felejthető (5. fejezet: ERR_HTTP_HEADERS_SENT), a throw viszont nem hagy rá lehetőséget. Ez a fejezet egyik legfontosabb gyakorlati haszna.

A webshop hibakódjai

Rögzítsük őket egy helyen, hogy a kliens is dokumentálva kapja:

KódStátuszMikor?
ERVENYTELEN_ID400Az azonosító nem szám vagy nem pozitív
HIANYZO_MEZO400Kötelező mező hiányzik a törzsből
ERVENYTELEN_JSON400A törzs nem érvényes JSON
TUL_NAGY_TORZS413A törzs nagyobb a megengedettnél
TERMEK_NEM_TALALHATO404Nincs ilyen azonosítójú termék
NINCS_VEGPONT404Nincs ilyen útvonal
SZERVERHIBA500Minden más

5Aszinkron hibák — mit kap el az Express 5?

Ez a fejezet legfontosabb — és legtöbb meglepetést okozó — szakasza.

✓ AZ EXPRESS ELKAPJA ✓throwszinkron kezelőben ✓throwasync kezelőben ✓throwasync middleware-ben ✓next(hiba)bárhonnan → a központi hibakezelőhöz kerül ✗ NEM KAPJA EL ✗ Vissza nem adott Promise Promise.reject(…) — nincs await → a kérés VÁLASZ NÉLKÜL lóg ✗ Hiba időzített visszahívásban setTimeout(() => { throw … }) → kiszökik a folyamatba a válasz már elment, a Node leállhat AZ UTOLSÓ VÉDŐVONAL — PROCESS-SZINTŰ HÁLÓK process.on("unhandledRejection", …) az elkapatlan Promise-elutasításokra process.on("uncaughtException", …) a mindenhonnan kiszökött hibákra — naplóz, majd kecsesen leáll
2. ábra — Négy elkapott és két elkapatlan eset. A jobb oldal a fejezet fő tanulsága.

Amit elkap

app.get("/api/products", async (req, res) => {
  const termekek = await adatbazisbolLekerdez();   // ha ez elhasal…
  res.json(termekek);                              // …ide nem jut el
});

Az Express 5 az async függvény által visszaadott Promise elutasítását magától a hibakezelőhöz továbbítja. Kipróbálva: 500-as válasz születik a saját hibakezelőnkből.

Amit NEM kap el

Két eset, és mindkettő csendben okoz bajt. Az eredmények:

a) Vissza nem adott Promise

app.get("/promise", (req, res) => {
  Promise.reject(new Error("elkapatlan promise"));   // ❌ nincs await, nincs return
});
!! unhandledRejection: elkapatlan promise
GET /promise   →   IDŐTÚLLÉPÉS — a kérés lóg

A kérés soha nem kap választ, mert a kezelőfüggvény sem válaszolt, sem next()-et nem hívott. Az Express nem lát semmit: a Promise nem az ő kezében van.

b) Hiba egy időzített visszahívásban

app.get("/timeout", (req, res) => {
  setTimeout(() => {
    throw new Error("callbackben dobott hiba");     // ❌ senki nem kapja el
  }, 10);
  res.json({ elment: true });
});
GET /timeout   →   200   {"elment":true}
!! uncaughtException: callbackben dobott hiba

A válasz elment, a hiba viszont kiszökött a folyamatba. Kezeletlen uncaughtException esetén a Node alapból leállítja a programot.

AZ ÖKÖLSZABÁLY

Az Express csak azt látja, amit a kezelőfüggvény visszaad. Ha egy aszinkron művelet elé nem írsz await-et (vagy nem adod vissza return-nel), az Express számára nem is létezik.

Elkapja az Express?

Nyolc kódrészlet. Döntsd el mindegyikről, hogy a hiba eljut-e a központi hibakezelőhöz — a visszajelzés megadja a következményt és a javítást is.

1 / 8Helyes: 0
…

Akkor kell-e try/catch?

Nem mindenhova. Két esetben igen:

// 1) Ha SAJÁT üzenetet vagy más státuszkódot akarsz
app.get("/api/products/:id", async (req, res) => {
  try {
    const termek = await szolgaltatas.termekAzonositoval(id);
    res.json(termek);
  } catch (hiba) {
    throw new HttpHiba(503, "Az adatbázis nem érhető el.", "ADATBAZIS_HIBA");
  }
});

// 2) Ha takarítani kell (fájl bezárása, tranzakció visszagörgetése)

Ha viszont csak annyit akarsz, hogy a hibából 500 legyen, hagyd el — az Express elintézi.

6A process-szintű hálók

A két „nem elkapott” esetre a Node ad utolsó védővonalat. Ez az index.js-be kerül:

// index.js
import app from "./src/app.js";
import { config } from "./src/config.js";

const szerver = app.listen(config.port, () => {
  console.log(`A szerver fut (${config.kornyezet}): http://localhost:${config.port}`);
});

process.on("unhandledRejection", (hiba) => {
  console.error("[VÉGZETES] Kezeletlen Promise-elutasítás:", hiba);
  szerver.close(() => process.exit(1));
});

process.on("uncaughtException", (hiba) => {
  console.error("[VÉGZETES] Kezeletlen kivétel:", hiba);
  szerver.close(() => process.exit(1));
});
EseményMikor lép működésbe?
unhandledRejectionEgy Promise elutasításra került, és senki nem kapta el
uncaughtExceptionEgy throw kiszökött minden try/catch-ből
MIÉRT ÁLLÍTJUK LE A PROGRAMOT?

Mert ilyenkor a program ismeretlen állapotba került: nem tudjuk, mi futott le és mi nem. Tovább futtatni kockázatosabb, mint újraindítani. A szerver.close() előbb kiszolgálja a már futó kéréseket, csak utána lép ki — ezt hívják kecses leállásnak (graceful shutdown).

Éles környezetben egy felügyelő program (a szolgáltató vagy egy folyamatkezelő) automatikusan újraindítja a szervert. Iskolai gépen a node --watch ugyanezt teszi.

7Fejlesztés vs. éles: mit mutatunk meg?

Az Express beépített hibakezelője már magától így viselkedik. Az eredmények ugyanarra a hibára:

app.get("/hiba", () => { throw new Error("bumm a részletekkel"); }) FEJLESZTÉS alapértelmezett Error: bumm a részletekkel at … (a teljes veremkiírás) ÉLES NODE_ENV=production Internal Server Error A NAPLÓ MINDKÉT ESETBEN UGYANAZ A fejlesztő a teljes képet a terminálból kapja meg — a kliens felé viszont éles környezetben semmi nem szivárog ki.
3. ábra — Ugyanaz a hiba, kétféle válasz. Az Express beépített kezelőjének válaszai.

A saját hibakezelőnknek is így kell tennie. A 7. fejezet config.js-e alapján:

import { config } from "../config.js";

export function hibakezelo(err, req, res, next) {
  console.error(`[HIBA] ${req.method} ${req.originalUrl}`, err);

  if (res.headersSent) return next(err);

  const statusz = err.status ?? 500;
  const fejlesztes = config.kornyezet !== "production";

  res.status(statusz).json({
    error: {
      message: statusz < 500 ? err.message : "Váratlan szerverhiba történt.",
      code: statusz < 500 ? (err.code ?? "SZERVERHIBA") : "SZERVERHIBA",
      ...(fejlesztes && statusz >= 500 ? { reszletek: err.message, stack: err.stack } : {})
    }
  });
}
RészMit csinál?
statusz < 500 ? … : …4xx-nél a pontos üzenet és kód megy ki, 5xx-nél általános szöveg és SZERVERHIBA (3. szakasz)
...(feltétel ? { … } : {})Feltételes mezők: csak akkor kerülnek bele az objektumba, ha a feltétel igaz
reszletek és stackCsak fejlesztéskor, és csak 5xx-nél
MIÉRT NEM MUTATJUK MEG ÉLESBEN?

Mert a hibaüzenet elárulhatja a belső szerkezetet: fájlneveket, mappaneveket, adatbázis-mezőket, néha még a lekérdezést is. Ez támadási felület. A fejlesztő a naplóból úgyis megkapja a teljes képet.

8A teljes kép: hova kerül minden?

webshop-api/
  index.js                     ← app.listen + a process-szintű hálók
  src/
    app.js                     ← a lánc összeállítása
    config.js
    middlewares/
      nem-talalhato.js         ← 404
      hibakezelo.js            ← a központi hibakezelő
    utils/
      HttpHiba.js              ← a saját hibaosztály
    routes/  controllers/  services/
// src/app.js — a teljes lánc
import express from "express";
import path from "node:path";
import termekRouter from "./routes/termek.routes.js";
import { nemTalalhato } from "./middlewares/nem-talalhato.js";
import { hibakezelo } from "./middlewares/hibakezelo.js";

const app = express();

app.use(express.json());                                                // 1) törzs
app.use(express.static(path.join(import.meta.dirname, "..", "public")));  // 2) statikus

app.use("/api/products", termekRouter);                                // 3) útvonalak

app.use(nemTalalhato);                                                  // 4) 404
app.use(hibakezelo);                                                    // 5) hibakezelő

export default app;

Mit lát a kliens? — összefoglaló

KérésStátuszVálasz
GET /api/products/42200a termék
GET /api/products/alma400{"error":{"message":"Az azonosító csak szám lehet.","code":"ERVENYTELEN_ID"}}
GET /api/products/999404{"error":{"message":"Nincs ilyen termék.","code":"TERMEK_NEM_TALALHATO"}}
GET /nincs-ilyen404{"error":{"message":"Nincs ilyen végpont: GET /nincs-ilyen","code":"NINCS_VEGPONT"}}
POST hibás JSON-nal400a törzs-feldolgozó hibája, ugyanabban a formátumban
bármi váratlan500{"error":{"message":"Váratlan szerverhiba történt.","code":"SZERVERHIBA"}}

Minden válasz ugyanabban a formátumban — ez az egész fejezet célja.

9Gyakori hibák

A hibakezelő soha nem fut le

app.use(hibakezelo);                      // ❌ az útvonalak ELŐTT
app.use("/api/products", termekRouter);

Tünet: a hibaválasz HTML, a saját JSON-formátumod helyett.
Megoldás: a hibakezelő a legvégére, a 404-kezelő után.

Három paraméter négy helyett

app.use((err, req, res) => { … });        // ❌ hiányzik a next

Tünet: ugyanaz — az Express közönséges middleware-nek nézi, és soha nem ad neki hibát.
Megoldás: mind a négy paraméter kiírása, akkor is, ha a next-et nem használod.

A 404-kezelő a hibakezelő UTÁN áll

app.use(hibakezelo);
app.use(nemTalalhato);                    // ❌

Tünet: a nem létező végpontokra a 404 megy ugyan, de a hibák is oda futnak be, mert a hibakezelő már lefutott előtte.
Megoldás: először nemTalalhato, aztán hibakezelo.

A kérés lóg, unhandledRejection a naplóban

app.get("/x", (req, res) => {
  szolgaltatas.valamiAszinkron();         // ❌ nincs await, nincs return
});

Megoldás: async kezelőfüggvény + await, vagy return a Promise elé.

ERR_HTTP_HEADERS_SENT a hibakezelőben

Ha a válasz már elment, mire a hiba keletkezett, a hibakezelő újabb hibát okozna.
Megoldás: a res.headersSent vizsgálata a kezelő elején.

Éles környezetben kiszivárog a veremkiírás

Tünet: a 500-as válaszban ott a fájlnév és a sor száma.
Megoldás: a NODE_ENV=production beállítása és a részletek elrejtése a hibakezelőben.

10Feladatok

Elméleti

F1⭐4xx vagy 5xx?

Sorold be mindegyiket, és indokold:

  • a) hiányzik a kötelező nev mező
  • b) elszállt az adatbázis-kapcsolat
  • c) elgépelt függvénynevet hívtál meg
  • d) nincs ilyen azonosítójú termék
  • e) a törzs nem érvényes JSON
  • f) undefined mezőre hivatkoztál
F2⭐Mi a sorrend?

Rakd helyes sorrendbe: hibakezelo, express.json(), app.use("/api/products", router), nemTalalhato, helmet(). Mindegyikhez írj egy mondatot, miért ott a helye!

F3⭐⭐Elkapja vagy nem?

Döntsd el mindegyikről, hogy az Express 5 a hibakezelőhöz továbbítja-e, és indokold:

a) app.get("/a", () => { throw new Error("x"); });
b) app.get("/b", async () => { throw new Error("x"); });
c) app.get("/c", (q, s) => { Promise.reject(new Error("x")); });
d) app.get("/d", (q, s) => { setTimeout(() => { throw new Error("x"); }, 10); });
e) app.get("/e", (q, s, n) => n(new Error("x")));
F4⭐⭐Hibakeresés

Mi a baj, és mi a tünete? (Két hibát keress: egy szerkezetit és egy biztonságit.)

export function hibakezelo(err, req, res) {
  res.status(err.status || 500).json({ error: { message: err.message } });
}
F5⭐⭐⭐Tervezz hibakatalógust

Egészítsd ki a 4. szakasz kódtáblázatát a rendelésekhez tartozó hibákkal (üres kosár, nem elérhető készlet, már kifizetett rendelés módosítása, más felhasználó rendelése). Mindegyikhez add meg a státuszkódot, a kódot és az üzenetet, és indokold a státuszkód-választást!

Gyakorlati

G1⭐404-kezelő

Készítsd el a nemTalalhato middleware-t a saját formátumodban, és bizonyítsd be REST Clienttel, hogy egy nem létező végpont JSON-t ad vissza, nem HTML-t.

G2⭐⭐Központi hibakezelő

Írd meg a hibakezelo middleware-t a 3. szakasz szerint (naplózás, headersSent-vizsgálat, err.status). Készíts egy szándékosan hibás végpontot (GET /api/bumm), és nézd meg, mit kap a kliens és mit ír a terminál!

G3⭐⭐Saját hibaosztály

Készítsd el a HttpHiba osztályt, és írd át vele a GET /api/products/:id végpontot úgy, hogy return res.status(…) helyett throw-t használjon. Ellenőrizd, hogy mindhárom eset (200, 400, 404) továbbra is helyesen működik!

G4⭐⭐Aszinkron hiba

Készíts egy async végpontot, amely egy szándékosan elhasaló műveletet hív (await Promise.reject(new Error("teszt"))). Bizonyítsd be, hogy try/catch nélkül is 500-as választ kapsz a saját hibakezelődből!

G5⭐⭐⭐Fejlesztés és éles

Egészítsd ki a hibakezelőt úgy, hogy 5xx esetén csak fejlesztéskor küldje el a reszletek és stack mezőket. Indítsd el a szervert egyszer NODE_ENV=development, egyszer NODE_ENV=production beállítással, és hasonlítsd össze a két választ! Állítsd be a process-szintű hálókat is.

11Önellenőrző kvíz

0 / 10 megválaszolva

12Összegzés

  1. Kétféle hiba van: a működési (4xx, a kliens megoldhatja) és a programozói (5xx, a fejlesztőnek szól). A státuszkód-választás ebből következik.
  2. A 404-kezelő minta nélküli middleware az útvonalak után; a központi hibakezelő négyparaméteres, és a lánc legvégén áll. Ebben a sorrendben.
  3. A hibakezelő három dolgot tesz: naplóz, megnézi a res.headersSent értékét, majd egységes JSON-választ küld.
  4. A saját HttpHiba osztály status és code mezőt hoz magával — így a throw new HttpHiba(404, …) írásmód elég, és nem felejthető el a return.
  5. Az Express 5 elkapja a szinkron és az async kezelőkben, valamint az async middleware-ekben dobott hibákat, és a next(hiba) hívást.
  6. Nem kapja el a vissza nem adott Promise elutasítását (a kérés lóg) és a setTimeout-visszahívásban dobott hibát (a folyamat leállhat).
  7. Ezekre a process-szintű hálók valók (unhandledRejection, uncaughtException), amelyek naplóznak, majd kecsesen leállítják a szervert.
  8. Éles környezetben a 5xx-es válasz nem tartalmazhat üzenetet és veremkiírást — azok csak a naplóba mennek.

13Fogalomtár

FogalomJelentés
Működési hibaSzámítottunk rá; a kliens meg tudja oldani. 4xx
Programozói hibaA kódunk hibás; a kliens nem tehet semmit. 5xx
404-kezelőMinta nélküli middleware a lánc végén, az útvonalak után
Központi hibakezelőNégyparaméteres middleware a lánc legvégén
err.statusA hibához tartozó státuszkód — a beépített kezelő is ezt használja
err.codeAz állandó, gépnek szóló hibakód
res.headersSentIgaz, ha a válasz már elment
unhandledRejectionNode-esemény: elutasított Promise, amit senki nem kapott el
uncaughtExceptionNode-esemény: minden try/catch-ből kiszökött hiba
Kecses leállásA futó kérések kiszolgálása, majd kilépés (szerver.close())
NODE_ENVKörnyezeti változó; a production érték elrejti a hibarészleteket
← Előző 7. Statikus fájlok és projektszerkezet