25 август 2025

Xatolarni qayta ishlash, "try..catch"

Dasturlashda qanchalik zo’r bo’lmasak, ba’zida bizning skriptlarimizda xatolar bo’ladi. Ular bizning xatolarimiz, kutilmagan foydalanuvchi kiritishi, serverning noto’g’ri javobi va boshqa minglab sabablarga ko’ra yuzaga kelishi mumkin.

Odatda, skript konsolga yozib, xatolik yuz berganda “o’ladi” (darhol to’xtaydi).

Ammo try..catch sintaksis konstruktsiyasi mavjud bo’lib, u xatolarni “ushlashga” imkon beradi va o’lish o’rniga yanada oqilona ishni bajaradi.

“try…catch” sintaksisi

try..catch konstruktsiyasi ikkita asosiy blokga ega: try va keyin catch:

try {

  // kod...

} catch (err) {

  // xatolarni qayta ishlash

}

U shunday ishlaydi:

  1. Birinchidan, try {...} dagi kod bajariladi.
  2. Agar xatolar bo’lmasa, catch(err) e’tiborga olinmaydi: bajarilish try tugashiga yetadi va keyin catch dan o’tib ketadi.
  3. Agar xato yuzaga kelsa, try bajarilishi to’xtatiladi va boshqaruv catch (err) boshiga oqib keladi. err o’zgaruvchani (buning uchun istalgan nomni ishlatishiz mumkin) xatolar obyekti bo’lib, unda nima bo’lganligi haqida batafsil ma’lumot mavjud.

Shunday qilib, try {…} bloki ichidagi xato skriptni o’ldirmaydi: biz uni catch da boshqarish imkoniyatiga egamiz.

Keling, ko’proq misollarni ko’rib chiqaylik.

  • Xatoliksiz misol: alert (1) va (2) ko’rsatadi:

    try {
    
      alert('try ning bajarilishi');  // (1) <--
    
      // ...bu erda hech qanday xato yo'q
    
      alert('try ning bajarilishi tugadi');   // (2) <--
    
    } catch (err) {
    
      alert("Catch e'tiborga olinmaydi, chunki xatolar yo'q"); // (3)
    
    }
    
    alert("...Keyin ijro davom etmoqda");
  • Xato bilan misol: (1) va (3):

    try {
    
      alert('try ning bajarilishi');  // (1) <--
    
      lalala; // error, variable is not defined!
    
      alert('try ning bajarilishi tugadi (yetib bormaydi)');  // (2)
    
    } catch (err) {
    
      alert(`Xato yuz berdi!`); // (3) <--
    
    }
    
    alert("...Keyin ijro davom etmoqda");
try..catch faqat ish vaqtidagi xatolar uchun ishlaydi

try..catch ishlashi uchun kod ishga tushirilishi kerak. Boshqacha qilib aytganda, u JavaScript-ga yaroqli bo’lishi kerak.

Agar kod sintaktik noto’g’ri bo’lsa, u ishlamaydi, masalan, unga mos kelmaydigan jingalak qavslar mavjud:

try {
  {{{{{{{{{{{{
} catch(e) {
  alert("Interpretator ushbu kodni tushunolmaydi, u yaroqsiz");
}

JavaScript interpretatori avval kodni o’qiydi, so’ngra uni bajaradi. O’qish iborasida yuzaga keladigan xatolar “parse-time” xatolari deb nomlanadi va ularni qaytarib bo’lmaydi (o’sha kod ichidan). Buning sababi interpretator kodni tushuna olmaydi.

Shunday qilib, try..catch faqat to’g’ri kodda yuzaga keladigan xatolarni ko’rib chiqishi mumkin. Bunday xatolar “ish vaqtidagi xatolar” yoki ba’zan “istisnolar” deb nomlanadi.

try..catch sinxron ravishda ishlaydi

Agar setTimeout singari “rejalashtirilgan” kodda istisno bo’lsa, try..catch uni ushlamaydi:

try {
  setTimeout(function() {
    noSuchVariable; // skript bu yerda o'ladi
  }, 1000);
} catch (e) {
  alert( "ishlamaydi" );
}

Buning sababi, try..catch funktsiyani rejalashtiradigan setTimeout chaqirig’ini aslida o’rab oladi. Ammo funktsiya o’zi keyinroq, interpretator allaqachon try..catch konstruktsiyasini tark etganda amalga oshiriladi.

Rejalashtirilgan funktsiyani istisno qilish uchun ushbu funktsiya ichida try..catch bo’lishi kerak:

setTimeout(function() {
  try {
    noSuchVariable; // try..catch xatoni ko'rib chiqadi!
  } catch {
    alert( "xato bu yerda aniqlandi!" );
  }
}, 1000);

Xato obyekti

Xato yuz berganda, JavaScript bu haqda batafsil ma’lumotlarni o’z ichiga olgan obyektni yaratadi. Keyin obyekt catch argumenti sifatida uzatiladi:

try {
  // ...
} catch(err) { // <-- "xato obyekti", err o'rniga boshqa so'z ishlatishi mumkin
  // ...
}

O’rnatilgan barcha xatolar uchun catch blokidagi xato obyekti ikkita asosiy xususiyatga ega:

name
Xato nomi. ReferenceError aniqlanmagan o’zgaruvchan uchun.
message
Xato tafsilotlari haqida matnli xabar.

Ko’pgina muhitlarda boshqa nostandart xususiyatlar mavjud. Eng ko’p ishlatiladigan va qo’llab-quvvatlanadigan narsalardan biri:

stack
Joriy chaqiruvlar to’plami: xatoga olib kelgan ichki chaqiruvlar ketma-ketligi haqida ma’lumotga ega matn. Nosozliklarni tuzatish maqsadida foydalaniladi.

Masalan:

try {
  lalala; // xato, o'zgaruvchan aniqlanmagan!
} catch (err) {
  alert(err.name); // ReferenceError
  alert(err.message); // lalala aniqlanmagan
  alert(err.stack); // ReferenceError: lalala aniqlanmagan ...

  // Xatolikni ham to'liq ko'rsatishi mumkin
  // Xato "ism: xabar" sifatida matnga aylantirildi
  alert(err); // ReferenceError: lalala aniqlanmagan
}

Ixtiyoriy “catch” bloki

Yaqinda qo'shilgan
Bu tilga yaqinda qo'shilgan narsa. Eski brauzerlarda polifilllar kerak bo'lishi mumkin.

Agar bizga xato tafsilotlari kerak bo’lmasa, catch uni o’tkazib yuborishi mumkin:

try {
  // ...
} catch {
  // xato obyekti chiqarib tashlandi
}

Foydalanish “try…catch”

Keling, try..catch ning haqiqiy hayotida ishlatilgan holatlarini ko’rib chiqaylik.

Bizga ma’lumki, JavaScript JSON bilan kodlangan qiymatlarni o’qish uchun JSON.parse(str) usulini qo’llab-quvvatlaydi.

Odatda u serverdan yoki boshqa manbadan tarmoq orqali olingan ma’lumotlarni dekodlash uchun ishlatiladi.

Biz uni olamiz va JSON.parse ni chaqiramiz, shunga o’xshash:

let json = '{"name":"John", "age": 30}'; // serverdan olingan ma'lumotlar

let user = JSON.parse(json); // matnni JS obyektiga aylantirish

// endi user - bu matndan xususiyatlarga ega bo'lgan obyekt
alert( user.name ); // John
alert( user.age );  // 30

JSON haqida batafsil ma’lumotni JSON usullari, toJSON bobida topishingiz mumkin.

Agar json noto’g’ri tuzilgan bo’lsa, JSON.parse xatoga yo’l qo’yadi, shuning uchun skript “o’ladi”.

Biz bu bilan qoniqishimiz kerakmi? Albatta yo’q!

Shu tarzda, agar ma’lumotlar bilan bog’liq biror narsa noto’g’ri bo’lsa, foydalanuvchi buni hech qachon bilmaydi (agar ular dasturchi konsolini ochmasa). Hech qanday xato xabari bo’lmagan holda skript “o’lsa” odamlarga haqiqatan ham yoqmaydi.

Xatoni boshqarish uchun try..catch dan foydalanamiz: