2.12-bob: Error handling — try/catch/finally, throw, custom error
2-QISM — JavaScript (0 dan chuqurgacha) · 12-mavzu
1. Kirish va motivatsiya
Hozirgacha deyarli har bobda try/catch ni sezdik (2.11 ayniqsa). Endi xatolarni boshqarishni to'liq, professional darajada o'rganamiz. Bu — havaskor va professional dasturchi farqini eng aniq ko'rsatadigan mavzu.
Yangi dasturchi "kod ishlasin" deb yozadi. Professional — "kod xato bo'lganda ham to'g'ri ishlasin" deb yozadi. Tarmoq uziladi, foydalanuvchi noto'g'ri ma'lumot kiritadi, fayl topilmaydi, DB javob bermaydi — bularning hammasi sodir bo'ladi. Savol — dasturingiz qulaydimi yoki chiroyli uddasidan chiqadimi.
O'xshatish: xato handling — bu havfsizlik to'ri (akrobat ostidagi). Akrobat yiqilmaslikka harakat qiladi, lekin yiqilsa — to'r uni tutadi. Tor bo'lmagan akrobat — beparvo. Error handling'siz dastur — har tomchi yomg'irda qulaydi.
Xato — dushman emas, balki dasturni mustahkam (robust) qiladigan vosita. Bu bob — 5.10 (Express error middleware), 8.6 (NestJS exception filter) va butun backend ishonchliligining poydevori.
2. Nazariya — chuqur tushuntirish
2.1. Xato turlari
JS'da ikki asosiy xato vaqti:
- Compile/Syntax xato — kod noto'g'ri yozilgan (qavs yopilmagan). Kod umuman ishlamaydi.
- Runtime xato — kod ishlaganda yuzaga keladi (
undefinedga murojaat, tarmoq uzilishi). Bularni boshqarish kerak.
Asosiy built-in xato turlari (har biri Errordan meros — 2.5):
| Xato | Qachon |
|---|---|
Error |
umumiy/asosiy |
TypeError |
noto'g'ri tur (undefined.x, funksiyani son kabi) |
ReferenceError |
mavjud bo'lmagan o'zgaruvchi (TDZ — 2.4) |
RangeError |
chegaradan tashqari (stack overflow — 0.1) |
SyntaxError |
noto'g'ri sintaksis (JSON.parse — 2.8) |
2.2. try/catch/finally
Xatoni "ushlash"ning asosiy mexanizmi:
try {
// xato yuz berishi mumkin bo'lgan kod
const data = JSON.parse(matn); // noto'g'ri JSON SyntaxError (2.8)
console.log(data);
} catch (xato) {
// xato yuz bersa, BU blok ishlaydi (dastur qulamaydi!)
console.error("Xato:", xato.message);
} finally {
// HAR HOLDA ishlaydi (xato bo'ldimi, yo'qmi) — tozalash uchun
console.log("Tugadi");
}try— xavfli kod.catch (xato)— xato ushlanadi; dastur qulamaydi, davom etadi.xato—Errorobyekti.finally— doim ishlaydi (resurs yopish, tozalash — ulanishni yopish, yuklanish indikatorini o'chirish).
2.3. Error obyekti
Ushlangan xato — Error obyekti; muhim xususiyatlari:
try {
null.x;
} catch (xato) {
console.log(xato.name); // "TypeError" — tur (2.1)
console.log(xato.message); // "Cannot read properties of null..." — tavsif
console.log(xato.stack); // qayerda yuz bergani (debug — 15.5)
}2.4. throw — o'zi xato "tashlash"
throw — ataylab xato chiqarish; bu joriy ishni to'xtatadi va eng yaqin catchga "sakraydi":
function yoshTekshir(yosh) {
if (typeof yosh !== "number") {
throw new TypeError("Yosh son bo'lsin"); // ataylab xato (2.1)
}
if (yosh < 0 || yosh > 150) {
throw new RangeError("Yosh 0–150 oralig'ida"); // chegara (2.1)
}
return yosh;
}
try {
yoshTekshir(-5);
} catch (e) {
console.log(`${e.name}: ${e.message}`); // "RangeError: Yosh 0–150..."
}Doim
Errorobyekti "tashlang" (throw new Error(...)), oddiy string emas (throw "xato").Errorobyektidaname,message,stackbor — debug uchun zarur.
2.5. Custom error class — o'z xato turlari
Katta loyihada o'z xato turlaringizni yaratish kerak (Errordan meros — 2.5, 2.10):
class ValidatsiyaXatosi extends Error {
constructor(maydon, xabar) {
super(xabar); // ota Error constructor (2.10: super)
this.name = "ValidatsiyaXatosi"; // xato nomi
this.maydon = maydon; // qo'shimcha ma'lumot
}
}
class TopilmadiXatosi extends Error {
constructor(resurs) {
super(`${resurs} topilmadi`);
this.name = "TopilmadiXatosi";
this.status = 404; // HTTP status 0.4-bob — backendda foydali
}
}
try {
throw new TopilmadiXatosi("Foydalanuvchi");
} catch (e) {
if (e instanceof TopilmadiXatosi) { // turini tekshir (2.1)
console.log(e.status, e.message); // 404 "Foydalanuvchi topilmadi"
}
}Nega custom error: turli xatolarni ajratib boshqarish (validatsiya ≠ tarmoq ≠ topilmadi); qo'shimcha ma'lumot (
status,maydon); backend'da HTTP statusga bog'lash (5.10, 8.6).instanceofbilan turini tekshirasiz.
2.6. Asinxron xato (2.11 bilan bog'lanish)
async/awaitda xato — oddiy try/catch bilan 2.11-bob:
async function userOl(id) {
try {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`); // 0.4 (2.11)
return await res.json();
} catch (xato) {
// tarmoq xatosi YOKI throw qilingan HTTP xato — ikkalasi ham bu yerda
console.error(xato.message);
throw xato; // yoki qayta tashla (yuqori qatlam boshqarsin)
}
}Promise'larda (.then) — .catch:
userOl(1).then(u => {...}).catch(e => console.error(e)); // (2.11)
UnhandledPromiseRejection2.11-bob: har asinxron ishningtry/catchyoki.catch'i bo'lsin — aks holda xato "yo'qoladi" va dastur (Node'da) qulashi mumkin.
2.7. Xatoni qayerda ushlash — strategiya
Eng muhim qaror: xatoni qayerda ushlash?
- Past qatlamda (funksiya ichida) — faqat shu yerda hal qila olsangiz ushlang; aks holda qayta tashlang (
throw) yoki umuman ushlamang — yuqori qatlam boshqarsin. - Yuqori qatlamda (UI, route handler) — foydalanuvchiga chiroyli xabar ko'rsating (5.10: global error handler).
// Xatoni "yutib yuborish" (eng yomon)
try { xavfli(); } catch (e) {} // jim — xato yo'qoldi, debug imkonsiz!
// Hech bo'lmasa log yoki qayta tashla
try { xavfli(); } catch (e) { console.error(e); throw e; }Bo'sh
catch— eng katta gunoh. Xatoni ushlab, hech narsa qilmaslik — uni yashiradi; keyin bug'ni topish imkonsiz. Hech bo'lmasa log qiling yoki qayta tashlang.
2.8. Defensive programming — xatoni oldini olish
Xatoni ushlashdan ko'ra, uni oldini olish afzal (0.6: edge case, 0.1: NaN):
// Kirishni tekshirish (validatsiya)
function bol(a, b) {
if (b === 0) throw new Error("Nolga bo'lib bo'lmaydi"); // oldini ol
return a / b;
}
// Mavjudlikni tekshirish (2.1)
const ism = user?.profil?.ism ?? "Noma'lum"; // optional chaining + nullish
// Tur tekshirish (2.1)
if (!Array.isArray(data)) throw new TypeError("Massiv kutilgan");3. Sintaksis — tez ma'lumotnoma
try {
// xavfli kod
} catch (xato) {
// xato.name, xato.message, xato.stack
} finally {
// doim ishlaydi
}
throw new Error("xabar"); // xato tashlash
throw new TypeError("..."); // maxsus tur
class MyError extends Error { // custom (2.5)
constructor(m) { super(m); this.name = "MyError"; }
}
e instanceof MyError // turini tekshirish
// async (2.6)
try { await f(); } catch (e) {}
p.then().catch(e => {});4. Batafsil kod namunalari
Misol 1 — try/catch/finally va Error obyekti
function jsonOqi(matn) {
try {
const data = JSON.parse(matn); // noto'g'ri SyntaxError (2.8)
return data;
} catch (xato) {
console.error(`${xato.name}: ${xato.message}`); // (2.3)
return null; // xavfsiz standart qiymat
} finally {
console.log("Parse urinishi tugadi"); // doim (2.2)
}
}
jsonOqi('{"ism":"Ali"}'); // {ism:"Ali"}
jsonOqi('buzuq json'); // null + xato logMisol 2 — throw va validatsiya (2.4, 2.8)
function userYarat({ ism, yosh, email }) {
if (!ism || ism.trim().length < 2) {
throw new Error("Ism kamida 2 belgi bo'lsin"); // 2.6: string metod
}
if (typeof yosh !== "number" || yosh < 0) {
throw new RangeError("Yosh musbat son bo'lsin"); // (2.1)
}
if (!email?.includes("@")) {
throw new Error("Email noto'g'ri"); // (2.6, 2.1)
}
return { ism, yosh, email };
}
try {
const u = userYarat({ ism: "A", yosh: 19, email: "a@b.uz" });
} catch (e) {
console.log("Validatsiya xatosi:", e.message); // "Ism kamida 2 belgi..."
}Misol 3 — Custom error va instanceof (2.5)
class TolovXatosi extends Error {
constructor(xabar, kod) {
super(xabar);
this.name = "TolovXatosi";
this.kod = kod; // qo'shimcha (masalan "MABLAG_YETMADI")
}
}
function tolov(balans, summa) {
if (summa > balans) {
throw new TolovXatosi("Mablag' yetarli emas", "MABLAG_YETMADI");
}
return balans - summa;
}
try {
tolov(100, 500);
} catch (e) {
if (e instanceof TolovXatosi) { // maxsus xatoni ajratib boshqar (2.5)
console.log(`To'lov xatosi [${e.kod}]: ${e.message}`);
} else {
throw e; // boshqa xatoni qayta tashla (2.7)
}
}Misol 4 — Asinxron xato boshqaruvi (2.6, 2.11)
class ApiXatosi extends Error {
constructor(status, xabar) { super(xabar); this.name = "ApiXatosi"; this.status = status; }
}
async function malumotOl(url) {
try {
const res = await fetch(url);
if (!res.ok) throw new ApiXatosi(res.status, `So'rov muvaffaqiyatsiz`); // 0.4
return await res.json();
} catch (xato) {
if (xato instanceof ApiXatosi && xato.status === 404) {
console.log("Topilmadi");
return null; // 404 — kutilgan, null qaytar
}
console.error("Kutilmagan xato:", xato.message); // tarmoq va h.k.
throw xato; // qayta tashla (yuqori qatlam — 2.7)
}
}5. To'g'ri va noto'g'ri holatlar
1) Bo'sh catch (xatoni yutib yuborish)
// xato yo'qoladi — debug imkonsiz (2.7)
try { ish(); } catch (e) {}
// hech bo'lmasa log + kerak bo'lsa qayta tashla
try { ish(); } catch (e) { console.error(e); throw e; }2) String tashlash (Error o'rniga)
// stack/name yo'q (2.4)
throw "Xato yuz berdi";
// Error obyekti
throw new Error("Xato yuz berdi");3) Hamma narsani bitta umumiy catch
// barcha xatoni bir xil boshqarish (validatsiya = tarmoq = bug)
try { ... } catch (e) { alert("Xato"); }
// turini ajrat (2.5)
catch (e) {
if (e instanceof ValidatsiyaXatosi) korsatMaydonXatosi(e);
else if (e instanceof ApiXatosi) korsatTarmoqXatosi(e);
else throw e; // noma'lumni qayta tashla
}4) Asinxronda .catch/try-catch unutish
// UnhandledPromiseRejection (2.11)
async function f() { await xavfli(); }
f(); // catch yo'q
//
f().catch(e => console.error(e));6. Keng tarqalgan xatolar va yechimlari
Xato 1 — catch xatoni ushlamaydi (asinxronda)
try { setTimeout(() => { throw new Error("x"); }, 100); } catch (e) {} // ushlamaydi!Sababi: callback keyin ishlaydi — try allaqachon tugagan (2.11: event loop). Yechimi: xatoni callback ichida ushlang, yoki Promise/async-await ishlating 2.6-bob.
Xato 2 — finallyda return catchni "yutadi"
Sababi: finallydagi return try/catchning natijasini/xatosini bekor qiladi. Yechimi: finallyni faqat tozalash uchun ishlating, return/throw qo'ymang.
Xato 3 — Xato messagesiz
catch (e) { console.log(e); } // [object Object] yoki tushunarsizSababi: Error obyekti noto'g'ri chiqarildi. Yechimi: e.message yoki e.stack 2.3-bob.
Xato 4 — Custom error namesiz / supersiz
Sababi: extends Errorda super(message) yoki this.name unutildi 2.5-bob. Yechimi: constructor'da super(m) + this.name = "...".
Xato 5 — Xatoni juda erta yoki juda kech ushlash
Sababi: noto'g'ri qatlamda 2.7-bob. Yechimi: past qatlam — hal qila olsangiz ushlang yoki qayta tashlang; yuqori (UI/route) — foydalanuvchiga ko'rsating.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Async 2.11-bob:
try/catchasync bilan;UnhandledPromiseRejection. - Express error middleware 5.10-bob: global error handler — barcha xatoni bir joyda.
- NestJS Exception Filters 8.6-bob: custom error HTTP javob (status — 2.5).
- Validatsiya 5.9-bob: Zod/Joi xatolari; custom validatsiya error.
- HTTP status 0.4-bob: custom error'da
status— 4xx/5xx ga bog'lash. - Logger 5.12-bob: xatoni log qilish (
stackbilan — 2.3). - Debugging 15.5-bob:
stacktrace bilan xatoni topish. - React Error Boundaries 11.12-bob: komponent xatolari.
8. Eng yaxshi amaliyotlar (best practices)
- Hech qachon bo'sh
catch— log qiling yoki qayta tashlang 2.7-bob. - Doim
Errorobyekti tashlang (throw new Error(...)), string emas 2.4-bob. - Custom error class'lar bilan turli xatolarni ajrating (
instanceof— 2.5). - Xatoni to'g'ri qatlamda ushlang — past: hal qiling yoki qayta tashlang; yuqori: foydalanuvchiga 2.7-bob.
finallyni faqat tozalash uchun (return/throwqo'ymang — 6-bo'lim).- Asinxronda
try/catch/.catch—UnhandledPromiseRejectiondan qoching 2.6-bob. - Defensive: oldini oling (validatsiya,
?., tur tekshirish — 2.8) — ushlashdan ko'ra afzal. - Foydalanuvchiga texnik xato emas, tushunarli xabar ko'rsating; texnik tafsilotni log qiling.
9. Amaliy loyiha: "Mustahkam Forma Validatori va API Klient"
Error handling'ni amalda mustahkamlovchi loyiha.
Maqsad
try/catch/finally, throw, custom error class va asinxron xato boshqaruvini ishlatib, xatoga chidamli (robust) tizim qurish.
Talablar (requirements)
- Custom error iyerarxiyasi:
AppError(asosiy), undanValidatsiyaXatosi(maydonli),ApiXatosi(statusli),TopilmadiXatosi(status 404) —extends Error+super+name2.5-bob. - Forma validatori: ism/email/parol/yoshni tekshirib, noto'g'ri bo'lsa
ValidatsiyaXatosithrow qiladi (qaysi maydon —maydonda) (Misol 2). xavfsizParse(matn):JSON.parsenitry/catchbilan o'rab, xato bo'lsanull(Misol 1).- API klient (
async):fetch+res.oktekshiruvi; 404TopilmadiXatosi, boshqaApiXatosi; tarmoq xatosi alohida (Misol 4, 2.6). instanceofbilan boshqarish: chaqiruvchi kod xato turiga qarab har xil munosabat (validatsiya maydonni ko'rsat; 404 "topilmadi"; boshqa umumiy) (2.5, 2.7).finally: har so'rovdan keyin "yuklanmoqda" indikatorini o'chiring (tozalash — 2.2).- Retry: API xatosida 2 marta qayta urining, keyin taslim bo'ling (2.11 bilan).
- To'g'ri qatlam: past funksiyalar
throwqiladi; yuqori (asosiy) funksiyatry/catchbilan foydalanuvchiga xabar 2.7-bob.
Maslahatlar (hint)
- Custom error:
class AppError extends Error { constructor(m){super(m); this.name=this.constructor.name;} }2.5-bob. - Validator: har tekshiruvda aniq
throw new ValidatsiyaXatosi(maydon, xabar). - API:
if (res.status === 404) throw new TopilmadiXatosi(...)(Misol 4). instanceofzanjiri: aniqdan umumiyga (ValidatsiyaXatosiApiXatosielse).- Retry: tsikl +
try { return ... } catch { agar oxirgi urinish bo'lsa throw }. - Bo'sh catch ishlatmang — har joyda log yoki qayta tashlang 2.7-bob.
"Tayyor" mezonlari (acceptance criteria)
- Custom error iyerarxiyasi (
extends Error,super,name) ishlaydi. - Validator noto'g'ri maydonda aniq
ValidatsiyaXatositashlaydi. -
xavfsizParsebuzuq JSON'da qulamaydi. - API klient 404/tarmoq/boshqa xatoni ajratadi.
-
instanceofbilan xato turiga qarab har xil munosabat. -
finallytozalashni bajaradi. - Retry ishlaydi; oxirida taslim bo'ladi.
- Hech qayerda bo'sh
catchyo'q; stringthrowyo'q.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda professional kodning belgisini — error handlingni o'rgandik:
- Xato turlari:
TypeError,ReferenceError,RangeError,SyntaxError(har biriErrordan meros). try/catch/finally: xavfli kod ushlash (qulamaydi)finally(doim, tozalash).throw new Error(...)(string emas!) — ataylab xato; Error obyekti (name/message/stack).- Custom error class (
extends Error+super+name) — turli xatolarni ajratish (instanceof), qo'shimcha ma'lumot (status). - Asinxron 2.11-bob:
try/catch/.catch;UnhandledPromiseRejectiondan qoching. - Strategiya: bo'sh catch yo'q; to'g'ri qatlamda ushlang; defensive (oldini oling).
Keyingi bob — 2.13-bob: Regular expressions (RegEx). Matn bilan ishlashda 2.6-bob — qidirish, tekshirish, almashtirish — RegEx eng kuchli quroldir. Email, telefon, parol validatsiyasi (2.12-dagi), matndan ma'lumot ajratish — hammasi RegEx bilan ancha qudratli bo'ladi.
Foydalanilgan rasmiy/ishonchli manbalar
- MDN Web Docs — Control flow and error handling,
try...catch,throw - MDN Web Docs —
Error(va turlari:TypeError,RangeError...) - MDN Web Docs — Error.prototype (name/message/stack), custom errors
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!