Promise bilan xatoliklarni boshqarish
Asinxron ishlarda xatoliklar muqarrar: tarmoq uzilishi, noto'g'ri ma'lumot, server xatosi. Promise xatoliklarni boshqarishning ancha qulay yo'lini beradi. Ushbu darsda .catch, xatoning zanjir bo'ylab "sakrashi", qayta tashlash va e'tiborsiz qolgan rad etishlarni ko'rib chiqamiz.
.catch xatolikni ushlaydi
Promise zanjiri uzun bo'lsa ham, xatolikni boshqarish oson: zanjir oxiriga bitta .catch qo'yish kifoya. U zanjirning istalgan joyida yuz bergan xatolikni ushlaydi:
new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("Ma'lumot yuklanmadi!"));
}, 1000);
})
.then(function (result) {
console.log(result); // ishlamaydi โ xato bo'ldi
})
.catch(function (error) {
console.log("Xato ushlandi: " + error.message); // Xato ushlandi: Ma'lumot yuklanmadi!
});
Reject bo'lgan Promise'da natija .thendan "sakrab o'tib", to'g'ridan-to'g'ri eng yaqin .catchga boradi.
Xatolik zanjir bo'ylab o'tishi
Xatoliklarni boshqarishdagi eng muhim tamoyil: reject (yoki tashlangan xato) zanjir bo'ylab eng yaqin .catchgacha "sakraydi". Oradagi barcha .thenlar o'tkazib yuboriladi.
new Promise(function (resolve, reject) {
resolve(1);
})
.then(function (result) {
console.log("Bosqich 1: " + result); // 1
throw new Error("Bosqich 1'da xato!"); // xato tashlaymiz
})
.then(function (result) {
console.log("Bosqich 2"); // O'TKAZIB YUBORILADI
})
.then(function (result) {
console.log("Bosqich 3"); // O'TKAZIB YUBORILADI
})
.catch(function (error) {
console.log("Ushlandi: " + error.message); // Ushlandi: Bosqich 1'da xato!
});
.then ichida throw qilingan xato ham, reject ham bir xil yo'l bilan boshqariladi โ ikkalasi ham Promise'ni rejected qiladi va keyingi .catchga uzatiladi. Ya'ni Promise ichidagi throw new Error(...) avtomatik reject(...)ga aylanadi.Bu โ juda qulay xususiyat. Uzun zanjirda xatolik qayerda bo'lishidan qat'i nazar, uni bitta joyda โ oxirgi .catchda ushlaymiz. Callback'dagi kabi har bosqichda if (error) yozish shart emas.
.catch'dan keyin zanjir davom etadi
.catch xatoni ushlab, uni "tuzatgach", zanjir normal (fulfilled) holatda davom etadi. Chunki .catch ham Promise qaytaradi, va agar u xato tashlamasa, natija muvaffaqiyatli hisoblanadi:
new Promise(function (resolve, reject) {
reject(new Error("Boshlang'ich xato"));
})
.catch(function (error) {
console.log("Xato tuzatildi: " + error.message);
return "zaxira qiymat"; // xatoni "yamab", normal qiymat qaytaramiz
})
.then(function (result) {
// Zanjir davom etadi โ endi normal holatda
console.log("Davom: " + result); // Davom: zaxira qiymat
});
Xatoni qayta tashlash (rethrowing)
Ba'zan .catch ichida xatoni ushlaymiz-u, lekin uni bartaraf eta olmaymiz โ masalan, kutilmagan boshqa turdagi xato. Bunday holda uni qayta tashlash (rethrow) mumkin, shunda u keyingi .catchga o'tadi:
new Promise(function (resolve, reject) {
reject(new Error("Tarmoq xatosi"));
})
.catch(function (error) {
if (error.message === "Tarmoq xatosi") {
console.log("Tarmoq xatosini boshqaramiz...");
// bu xatoni hal qila olamiz โ davom etamiz
} else {
// hal qila olmaymiz โ qayta tashlaymiz
throw error;
}
})
.then(function () {
console.log("Tarmoq xatosi hal qilingach bu ishlaydi");
})
.catch(function (error) {
// Faqat qayta tashlangan (hal qilinmagan) xatolar bu yerga keladi
console.log("Hal qilinmagan xato: " + error.message);
});
Qoida sodda: agar .catch ichida throw qilsangiz โ nazorat keyingi .catchga o'tadi. Agar oddiy qaytsa (throw qilmasa) โ zanjir normal davom etadi. Bu try...catchning "agar hal qila olmasam, yuqoriga uzataman" tamoyiliga o'xshaydi.
Ishlov berilmagan rad etishlar (unhandledrejection)
Agar Promise reject bo'lsa-yu, uni ushlaydigan hech qanday .catch bo'lmasa nima bo'ladi? Xato "tiqilib" qoladi โ dastur bu haqda bilmay qoladi. Buni sezish uchun maxsus global hodisa bor: unhandledrejection.
// Bu Promise reject bo'ladi, ammo .catch YO'Q!
new Promise(function (resolve, reject) {
reject(new Error("E'tiborsiz qolgan xato"));
});
// .then/.catch qo'shilmagan
// Brauzerda global hodisa ishga tushadi:
window.addEventListener("unhandledrejection", function (event) {
console.log("Ishlov berilmagan rad etish!");
console.log(event.promise); // muammoli Promise obyekti
console.log(event.reason); // xato obyekti (Error)
});
unhandledrejection hodisasi โ brauzer standartining bir qismi. U hech qayerda ushlanmagan Promise xatosi bo'lganda ishga tushadi. Hodisa obyektining ikki muhim xususiyati bor:
event.promiseโ xatolik yuz bergan Promise obyekti;event.reasonโ rad etish sababi (odatdaErrorobyekti).
process.on("unhandledRejection", handler) orqali ushlanadi. Nomlanishi ozgina farq qiladi (bosh harflar), lekin g'oya bir xil..catchni bildiradi. Har bir asinxron zanjir oxirida albatta .catch bo'lishini ta'minlang โ bu xatoni "yashirin" qolishidan saqlaydi.Amaliy misol: xatoni ushlab, tiklanish
Sodda sinxron-o'xshash misol bilan "xato → catch → davom" oqimini mustahkamlaymiz. Bu yerda darhol reject bo'lgan Promise ishlatilgan, natija konsolda ko'rinadi:
E'tibor bering: birinchi .catch xatoni ushlab, 42 qaytardi. Shundan so'ng zanjir normal davom etdi (42 → 50). Oxirgi .catch esa ishlamaydi, chunki hech qanday hal qilinmagan xato qolmadi.
Xulosa
.catchzanjirning istalgan joyidagi xatolikni ushlaydi โ uni oxiriga qo'yish kifoya;- Reject yoki
throwqilingan xato eng yaqin.catchgacha sakraydi, oradagi.thenlar o'tkazib yuboriladi; - Promise ichidagi
throwavtomatikrejectga aylanadi; .catchxatoni "yamab" bo'lgach, zanjir normal davom etadi;.catchichidathrowqilsangiz โ xato keyingi.catchga uzatiladi (qayta tashlash);- Ushlanmagan xato unhandledrejection hodisasini keltirib chiqaradi โ har zanjirda
.catchbo'lsin.