Express xatolarni boshqarish
Hozirgacha yozgan kodimiz hamma narsa joyida ketishiga ishonadi. Lekin
foydalanuvchi mavjud bo’lmagan manzilni so’raydi, id o’rniga harf
yozadi, fayl o’qilmay qoladi. Bu holatlarni oldindan qamramasangiz,
Express o’zining xunuk standart javobini beradi — yoki bundan yomoni,
server butunlay to’xtaydi.
Standart javob nimasi bilan yomon
Marshrutlash darsida ko’rgan javobni eslang:
curl http://localhost:3000/hello
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Error</title></head>
<body><pre>Cannot GET /hello</pre></body>
</html>
Ikki muammo bor. Birinchisi — javob inglizcha HTML, sayt tilida emas.
Ikkinchisi jiddiyroq: agar bu API bo’lsa, mijoz JSON kutgan edi,
HTML keldi. response.json() bilan o’qishga urinsa, xato chiqadi.
O’z 404 javobingiz
Yechim — hamma marshrutdan keyin turadigan app.use():
const express = require("express");
const app = express();
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
// Yuqoridagi marshrutlarning hech biri mos kelmasa, shu yerga tushadi
app.use((request, response) => {
response.status(404).json({ error: "Bunday manzil topilmadi" });
});
app.listen(3000, () => {
console.log("Server ishga tushdi: http://localhost:3000");
});
curl -i http://localhost:3000/hello
HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
{"error":"Bunday manzil topilmadi"}
Mexanizm middleware darsidan tanish: Express
zanjirni tartib bilan yuradi. So’rov hamma marshrutdan o’tib, hech
qayerda javob olmasa, oxirgi app.use() ga yetib keladi.
Xato middleware’i: to’rt parametr
404 — “topilmadi”. Undan boshqa xatolar ham bor: kod ichida nimadir
buzildi. Express ularni alohida turdagi middleware bilan ushlaydi.
Bu Express’dagi eng ko’p e’tibordan chetda qoladigan tafsilot:
// ❌ Uch parametr — oddiy middleware, xatoni ushlamaydi
app.use((request, response, next) => { });
// ✅ To'rt parametr — xato middleware'i
app.use((err, request, response, next) => { });
To’liq misol:
const express = require("express");
const app = express();
app.get("/tasks", (request, response) => {
response.send("Vazifalar ro'yxati");
});
// 404 — manzil topilmadi
app.use((request, response) => {
response.status(404).json({ error: "Bunday manzil topilmadi" });
});
// Xato ishlovchisi — hammasidan keyin
app.use((err, request, response, next) => {
// Tafsilotni faqat serverning terminaliga yozamiz
console.error(err.message);
response.status(500).json({ error: "Serverda xato yuz berdi" });
});
app.listen(3000, () => {
console.log("Server ishga tushdi: http://localhost:3000");
});
Tartib qat’iy: marshrutlar → 404 → xato middleware’i.
next(err) bilan xatoni uzatish
Xato middleware’iga qanday borib tushiladi? next() ga argument berib.
const tasks = [
{ id: 1, title: "Kitob o'qish", isDone: false },
{ id: 2, title: "Kod yozish", isDone: true },
];
app.get("/api/tasks/:id", (request, response, next) => {
const id = Number(request.params.id);
if (Number.isNaN(id)) {
// Foydalanuvchi xatosi — darhol javob beramiz
return response.status(400).json({ error: "id son bo'lishi kerak" });
}
const task = tasks.find((item) => item.id === id);
if (!task) {
return response.status(404).json({ error: "Vazifa topilmadi" });
}
response.json(task);
});
Qoidani eslab qoling:
next() shakli |
Nima bo’ladi |
|---|---|
next() |
Navbatdagi oddiy middleware’ga o’tadi |
next(err) |
To’g’ridan-to’g’ri xato middleware’iga sakraydi |
next(err) chaqirilganda oradagi hamma oddiy middleware chetlab
o’tiladi. Buni ko’rish uchun ataylab xato chiqaramiz:
app.get("/boom", (request, response, next) => {
const error = new Error("Sinov uchun ataylab chiqarilgan xato");
next(error);
});
curl -i http://localhost:3000/boom
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{"error":"Serverda xato yuz berdi"}
Server terminalida esa:
Sinov uchun ataylab chiqarilgan xato
Foydalanuvchi umumiy xabarni, siz aniq sababni ko’rdingiz.
Sinxron xato o’zi ushlanadi
Marshrut ichida oddiy xato yuz bersa, Express uni o’zi tutadi:
app.get("/sync-error", (request, response) => {
// Mavjud bo'lmagan funksiya chaqirilyapti
const result = calculateTotal();
response.json({ result: result });
});
Bu manzilni so’rasangiz, server yiqilmaydi — xato middleware’i
ishlaydi va 500 qaytaradi. Express marshrut funksiyasini try/catch
ichida chaqiradi.
Lekin bu himoya faqat sinxron kodga tegishli.
Async marshrutdagi tuzoq
Asinxron kodda vaziyat boshqacha:
const fs = require("fs/promises");
// ❌ Xato ushlanmaydi
app.get("/report", async (request, response) => {
const text = await fs.readFile("report.txt", "utf-8");
response.send(text);
});
report.txt fayli bo’lmasa, readFile xato beradi. Express uni
ko’rmaydi, chunki xato async funksiya ichidagi Promise’da yuz beradi.
Yechim — try/catch va next(error):
const fs = require("fs/promises");
// ✅ Xato ushlanadi va uzatiladi
app.get("/report", async (request, response, next) => {
try {
const text = await fs.readFile("report.txt", "utf-8");
response.send(text);
} catch (error) {
next(error);
}
});
Fayl bo’lmasa:
curl -i http://localhost:3000/report
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=utf-8
{"error":"Serverda xato yuz berdi"}
Server ishlashda davom etadi. try/catch va async/await ishlashi
async/await darsida va
xatolar darsida ko’rilgan.
Holat kodini xatoga biriktirish
Hamma xato 500 emas. Kodni xato obyektiga yozib qo’yish mumkin:
app.get("/api/tasks/:id", (request, response, next) => {
const id = Number(request.params.id);
if (Number.isNaN(id)) {
const error = new Error("id son bo'lishi kerak");
error.status = 400;
return next(error);
}
const task = tasks.find((item) => item.id === id);
if (!task) {
const error = new Error("Vazifa topilmadi");
error.status = 404;
return next(error);
}
response.json(task);
});
// Xato middleware'i kodni o'qiydi
app.use((err, request, response, next) => {
const status = err.status || 500;
// 500 bo'lsa — bizning xatomiz, terminalga to'liq yozamiz
if (status === 500) {
console.error(err);
}
response.status(status).json({ error: err.message });
});
Bu yerda err.message javobga tushyapti — lekin faqat biz o’zimiz
yozgan xabarlar uchun. 500 holatida xabar kutilmagan manbadan
kelishi mumkin, shuning uchun uni umumiy matnga almashtirish xavfsizroq:
app.use((err, request, response, next) => {
const status = err.status || 500;
if (status === 500) {
console.error(err);
return response.status(500).json({ error: "Serverda xato yuz berdi" });
}
response.status(status).json({ error: err.message });
});
curl -i http://localhost:3000/api/tasks/abc
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{"error":"id son bo'lishi kerak"}
To’liq tartib
Yakuniy fayl tuzilishi shunday bo’ladi:
const express = require("express");
const app = express();
app.use(express.json()); // 1. Kirish middleware'lari
app.get("/tasks", handler); // 2. Marshrutlar
app.use(notFoundHandler); // 3. 404
app.use(errorHandler); // 4. Xato ishlovchisi
app.listen(3000);
Yuqoridagi qatorlardagi handler, notFoundHandler va errorHandler —
oldingi bo’limlarda yozilgan funksiyalar. Tartib o’zgarsa, tizim
buziladi: 404 yuqorida bo’lsa hamma so’rovni yutadi, xato middleware’i
yuqorida bo’lsa hech qachon chaqirilmaydi.
Amaliy mashq
express-app loyihasida davom eting:
- Hamma marshrutdan keyin
404middleware’ini qo’shib, mavjud bo’lmagan manzilnicurl -ibilan so’rang; 404middleware’ini marshrutlardan yuqoriga ko’chiring va hamma so’rov404olishini ko’ring, so’ng joyiga qaytaring;- To’rt parametrli xato middleware’ini yozing va
/boommarshrutidanext(new Error("..."))bilan sinang; - Xato middleware’idan bitta parametrni olib tashlab, u ishlamay qolishini tekshiring;
fs/promisesbilan mavjud bo’lmagan faylni o’qiydiganasyncmarshrut yozing — avvaltry/catchsiz, keyin u bilan;error.status = 404biriktirib, xato middleware’i to’g’ri kodni qaytarishini tasdiqlang.
4-qadam eng muhimi: xato middleware’i parametrlar soni bilan aniqlanishini bir marta ko’rsangiz, uni boshqa unutmaysiz.
Qisqacha xulosa
- Standart
Cannot GETjavobi inglizcha HTML — API uchun yaramaydi. 404middleware’i hamma marshrutdan keyin,app.listen()dan oldin turadi.- Xato middleware’i to’rt parametrli bo’lishi shart:
(err, request, response, next). next(err)oddiy middleware’larni chetlab, to’g’ridan-to’g’ri xato ishlovchisiga o’tadi.- Sinxron xatoni Express o’zi ushlaydi,
asyncmarshrutda esatry/catchvanext(error)sizning zimmangizda. - Xato tafsiloti va
stackfaqat terminalga yoziladi — foydalanuvchiga umumiy xabar boradi. err.statusbiriktirilsa, bitta ishlovchi turli holat kodlarini qaytara oladi.
Keyingi darsda CRUD API — beshta endpoint yozib, ma’lumot qo’shish, o’qish, yangilash va o’chirishni amalda ko’ramiz.