Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Ushlanmagan xato nima
- 2.1 Sinxron xato: Uncaught
- 2.2 Asinxron xato: Uncaught (in promise)
- 2.3 try/catch nega ushlamadi
- 3. Brauzer: global tinglovchilar
- 3.1 Oxirgi himoya chizig'i
- 3.2 Foydalanuvchiga aytish
- 3.3 unhandledrejection hodisasi ichida nima bor
- 3.4 preventDefault() — "men hal qildim"
- 3.5 error hodisasi va window.onerror
- 3.6 Uchta nozik holat
- 4. Node: dastur to'xtaydi
- 4.1 Brauzerdan katta farq
- 4.2 process.on: oxirgi chiziq Node'da
- 4.3 Qayd qiling — va to'xtating
- 5. Xatolarni qayd etish (loglash)
- 5.1 Nimani yozish kerak
- 5.2 Yuborish va cheklash
- 5.3 Tayyor xizmatlar
- 6. Hujumchi nigohi
- 7. Ko'p uchraydigan xatolar
- 7.1 Global tinglovchini catch o'rniga ishlatish
- 7.2 await siz try
- 7.3 uncaughtException dan keyin davom etish
- 7.4 Tinglovchi ichidagi xato
- 7.5 Har doim preventDefault()
- 8. Mashqlar
- 1-mashq (oson): Ushlanadimi?
- 2-mashq (o'rta): Bir martalik ogohlantirish
- 3-mashq (qiyin): Xato kuzatuvchi
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript ushlanmagan xatolar: unhandledrejection, window.onerror va process.on
Qisqacha: Hech qaysi
try/catchushlamagan xato ushlanmagan deyiladi. Brauzer uni konsolgaUncaught ...(Promise bo'lsa —Uncaught (in promise) ...) deb yozadi va sahifa ishlashda davom etadi. Node esa dasturni to'xtatadi. Oxirgi himoya chizig'i — global tinglovchilar: brauzerdawindow.addEventListener("error", ...)va"unhandledrejection", Node'daprocess.on("uncaughtException")va"unhandledRejection". Ular xatoni tuzatmaydi — qayd qiladi va foydalanuvchiga tushunarli xabar beradi.
Bu darsda
- Ushlanmagan xato va ushlanmagan rad etilish (rejection) nima ekanini, konsoldagi
UncaughtvaUncaught (in promise)qayerdan kelishini tushuntira olasiz. - Brauzerda
errorvaunhandledrejectionhodisalarini tinglay olasiz,event.preventDefault()nimani o'zgartirishini bilasiz. - Node'da
process.on("uncaughtException")va"unhandledRejection"bilan ishlay olasiz va ulardan keyin nega dasturni to'xtatish kerakligini tushuntira olasiz. - Xatolarni foydali qilib qayd etadigan (loglaydigan) kichik funksiya yoza olasiz.
Oldin bilishingiz kerak: try / catch / finally, Xato strategiyasi, async / await, Asinxron iteratsiya.
1. Nega bu kerak?
Juma kuni kechqurun «Bahor» sayti orqali bron qilish to'xtab qoldi. Mehmonlar «Bron qilish» tugmasini bosadi — hech narsa bo'lmaydi. Ekranda xato yo'q, sahifa "tirik" ko'rinadi. Jasur aka buni ertasi kuni, bir necha mehmon telefon qilgandan keyin bildi.
Sardor DevTools'ni ochdi va konsolda qizil qatorni ko'rdi:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'sana')Xato bir kun oldin, yangi kod bilan paydo bo'lgan edi. Lekin uni faqat konsolni ochgan odam ko'radi — mehmonlar esa konsolni ochmaydi.
Bu darsda ikki savolga javob beramiz:
- Hech kim ushlamagan xato qayerga "ketadi" va brauzer hamda Node u bilan nima qiladi?
- Bunday xatolarni qanday qilib bilib turish mumkin — foydalanuvchi telefon qilishidan oldin?
Xato strategiyasi darsida "dasturchi xatosini ushlab yashirmang, qayta tashlang" degan edik va va'da bergandik: hech kim ushlamagan xatolar uchun "oxirgi himoya chizig'i" bor. Bugun shu chiziqni quramiz.
2. Ushlanmagan xato nima
2.1 Sinxron xato: Uncaught
throw va Error obyekti darsidan bilasiz: xato tashlanganda JavaScript chaqiruvlar stekida yuqoriga qarab eng yaqin try/catch ni qidiradi. Topsa — catch bajariladi. Stekning eng tagigacha borib, hech qanday catch topmasa — xato ushlanmagan (uncaught) bo'ladi.
Brauzerda nima bo'lishini ko'ramiz. Sahifada ikkita <script> bor, birinchisi xato bilan tugaydi:
<p>Ikki skript: biri xato bilan tugaydi.</p>
<script>
console.log("1-skript boshlandi");
const menyu = null;
console.log(menyu.taomlar);
console.log("Bu qator chiqmaydi");
</script>
<script>
console.log("2-skript ishladi");
</script>Konsolda:
1-skript boshlandi
Uncaught TypeError: Cannot read properties of null (reading 'taomlar')
2-skript ishladiUch narsaga qarang:
Uncaught— "ushlanmagan". Brauzer xatoning oldiga shu so'zni qo'shadi: "buni hech kim ushlamadi". Xatoning o'zi —TypeError: Cannot read properties of null (reading 'taomlar'), ya'ni "nullningtaomlarxususiyatini o'qib bo'lmaydi".- Birinchi skript to'xtadi.
Bu qator chiqmaydihaqiqatan chiqmadi: xatodan keyingi kod bajarilmaydi. - Sahifa yashashda davom etdi. Ikkinchi skript ishladi. Brauzer faqat joriy task'ni to'xtatadi (Event loop). Keyingi task'lar — boshqa skriptlar, taymerlar, bosishlar — odatdagidek bajariladi.
Oxirgi nuqta muhim. Shuning uchun xato "ko'rinmaydi": sahifa ishlab turibdi, faqat bitta tugma yoki bitta funksiya jim buzilgan.
2.2 Asinxron xato: Uncaught (in promise)
Promise rad etilsa (rejected) va unga hech kim catch ulamasa, bu ham ushlanmagan xato — aniqrog'i, ushlanmagan rad etilish (unhandled rejection):
<p>Menyu yangilanmoqda...</p>
<script>
async function menyuniYangila() {
throw new Error("Server javob bermadi");
}
menyuniYangila();
setTimeout(() => console.log("Sahifa ishlayapti"), 100);
</script>Konsolda:
Uncaught (in promise) Error: Server javob bermadi
Sahifa ishlayaptiasync funksiya ichidagi throw funksiyani to'xtatmaydi — u funksiya qaytargan Promise'ni rad etadi (async / await). menyuniYangila() ni chaqirgan kod natijani await ham qilmadi, catch ham ulamadi. Shuning uchun brauzer "Promise ichida ushlanmagan" deb yozdi.
Qachon "ushlanmagan" deb hisoblanadi? Brauzer Promise rad etilgandan keyin microtask navbati bo'shashini kutadi (Event loop). Shu paytgacha catch ulanmasa — xabar chiqaradi. Ya'ni catch ni keyinroq, masalan taymer ichida ulash — kechikkan bo'ladi.
Tekshirib ko'ring:
Uncaught TypeErrorvaUncaught (in promise) TypeError— farqi nimada?
Javob
Birinchisi — oddiy, sinxron kodda tashlangan va hech qaysi try/catch ushlamagan xato. Ikkinchisi — rad etilgan Promise, unga hech kim catch (yoki try/catch ichida await) ulamagan. Xatoning o'zi bir xil bo'lishi mumkin; farq — u qayerda "yo'qolgani"da.
2.3 try/catch nega ushlamadi
try / catch / finally darsida bir tuzoqni ko'rgan edik: try taymer ichidagi xatoni ushlamaydi. Asinxron kodda bu tuzoq ko'p shaklda uchraydi:
async function bronniSaqla() {
throw new Error("Sana noto'g'ri");
}
try {
bronniSaqla();
} catch (xato) {
console.log("Ushlandi:", xato.message);
}Ushlandi chiqmaydi. bronniSaqla() xato tashlamaydi — u darhol rad etilgan Promise qaytaradi. try bloki muvaffaqiyatli tugaydi, rad etilish esa keyinroq, try dan tashqarida "uchib yuradi" — bu async / await darsidagi "suzib yurgan" (floating) Promise.
Tuzatish — await va async funksiya:
async function bronniSaqla() {
throw new Error("Sana noto'g'ri");
}
async function bronQil() {
try {
await bronniSaqla();
} catch (xato) {
console.log("Ushlandi:", xato.message);
}
}
bronQil();Konsolda:
Ushlandi: Sana noto'g'riawait rad etilgan Promise'ni yana throw ga aylantiradi — endi u try ichida sodir bo'ladi. Asinxron iteratsiya darsidagi Promise'lar massivi ham shu oila: rad etilgan Promise sikl unga yetib kelgunicha "egasiz" turdi.
3. Brauzer: global tinglovchilar
3.1 Oxirgi himoya chizig'i
Ushlanmagan xato bo'lganda brauzer konsolga yozishdan oldin window da hodisa chiqaradi. Uni tinglab, xatoni o'zingiz ham "ko'rishingiz" mumkin:
error— sinxron ushlanmagan xato uchun (va resurs yuklanmaganda — buni keyinroq ko'ramiz).unhandledrejection— ushlanmagan rad etilish uchun.
Sxemada xatoning yo'li:
flowchart TD
X["Xato tashlandi"] --> T{"Yaqinida try/catch<br/>yoki .catch bormi?"}
T -- "ha" --> C["catch bajariladi<br/>(xato ushlandi)"]
T -- "yo'q" --> P{"Promise ichidami?"}
P -- "yo'q" --> E["window: error<br/>hodisasi"]
P -- "ha" --> U["window: unhandledrejection<br/>hodisasi"]
E --> D{"preventDefault()<br/>chaqirildimi?"}
U --> D
D -- "yo'q" --> K["Konsolda: Uncaught ..."]
D -- "ha" --> J["Konsol jim"]Ko'ryapsizmi: global tinglovchi catch ning o'rnini bosmaydi. U xato allaqachon yo'qolgandan keyin ishlaydi. Funksiya to'xtagan, bron saqlanmagan. Tinglovchi faqat ikki ish qila oladi: xatoni qayd etish va foydalanuvchiga aytish.
3.2 Foydalanuvchiga aytish
Sardor «Bahor» sahifasiga global tinglovchi qo'shdi. Kutilmagan xato bo'lsa, sahifa tepasida tushunarli xabar chiqadi:
<style>
body { font: 1rem/1.5 system-ui, sans-serif; margin: 1rem; }
.ogohlantirish {
background: #fde8e8; color: #7a1010;
border: 1px solid #f3b4b4; border-radius: 0.5rem;
padding: 0.5rem 0.75rem;
}
</style>
<p id="ogohlantirish" class="ogohlantirish" role="alert" hidden></p>
<h1>«Bahor» — bron</h1>
<p>Bron formasi shu yerda.</p>
<script>
const ogohlantirish = document.getElementById("ogohlantirish");
function xabarniKorsat() {
ogohlantirish.textContent =
"Nimadir noto'g'ri ketdi. Sahifani yangilang.";
ogohlantirish.hidden = false;
}
window.addEventListener("error", xabarniKorsat);
window.addEventListener("unhandledrejection", xabarniKorsat);
async function bronlarniYukla() {
const javob = undefined;
return javob.sana;
}
bronlarniYukla();
</script>Konsolda:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'sana')Endi mehmon jim buzilgan sahifa o'rniga aniq xabarni ko'radi va nima qilishni biladi. role="alert" — ekran o'quvchi (Malika ishlatadigan NVDA) xabarni darhol ovoz chiqarib o'qiydi.
Konsoldagi qizil qator joyida qoldi: tinglovchi xatoni ko'rdi, lekin brauzerning o'z xabarini to'xtatmadi. Bu yaxshi — dasturchi DevTools'ni ochganda xatoni baribir ko'radi.
Maslahat: Global xabar — "favqulodda chiroq". Har bir kutilgan xato (server band, internet yo'q) uchun esa o'z joyida
try/catchva aniq xabar bo'lsin: "Internet yo'q — bron saqlanmadi, qayta urining". Global tinglovchiga faqat siz kutmagan xatolar yetib borishi kerak.
3.3 unhandledrejection hodisasi ichida nima bor
Tinglovchi PromiseRejectionEvent obyektini oladi. Ikkita asosiy xususiyati:
event.reason— rad etilish sababi. OdatdaErrorobyekti, lekinPromise.reject("matn")bo'lsa — oddiy satr. Shuning uchunevent.reason.messagedeb to'g'ridan-to'g'ri yozish xavfli.event.promise— rad etilgan Promise'ning o'zi.
window.addEventListener("unhandledrejection", (event) => {
console.log("Ushlandi:", event.reason.message);
});
Promise.reject(new Error("Server javob bermadi"));Konsolda (Chrome 154):
Ushlandi: Server javob bermadi
Uncaught (in promise) Error: Server javob bermadiTartibga e'tibor bering: avval sizning tinglovchingiz, keyin brauzerning qizil xabari. Brauzer xabarni hodisadan keyin chiqaradi — chunki tinglovchi uni bekor qilishi mumkin.
Diqqat: Bu va keyingi bloklar ostida «Ishga tushir» tugmasi yo'q: ular
windowning global hodisalarini tinglaydi, sayt esa kodni o'z oynasida bajaradi. Ularni o'z sahifangizda (Live Server bilan) yoki DevTools konsolida sinang. Chiqishlar Chrome 154 da tekshirilgan.
3.4 preventDefault() — "men hal qildim"
Event obyekti va standart harakatlar darsida preventDefault() formaning yuborilishini to'xtatgan edi. Bu yerda u brauzerning standart harakatini — konsolga qizil xabar yozishni — to'xtatadi:
window.addEventListener("unhandledrejection", (event) => {
event.preventDefault();
console.log("Ushlandi:", event.reason.message);
});
Promise.reject(new Error("Server javob bermadi"));Konsolda (Chrome 154):
Ushlandi: Server javob bermadiQizil qator yo'q. Bu qachon kerak? Siz xatoni o'zingiz to'liq qayd qilganingizda va konsolda ikki marta ko'rinishini xohlamaganingizda. Ehtiyot bo'ling: preventDefault() ni har doim chaqirsangiz, dasturchi DevTools'da hech qanday xatoni ko'rmaydi. Ko'p jamoalar uni ishlatmaydi — konsoldagi xabar zarar qilmaydi.
3.5 error hodisasi va window.onerror
Sinxron xatolar uchun hodisa — error, obyekti — ErrorEvent. Unda ko'proq ma'lumot bor:
window.addEventListener("error", (event) => {
console.log(event.message);
console.log(event.filename, event.lineno, event.colno);
console.log(event.error instanceof Error);
});
setTimeout(() => {
const bron = null;
console.log(bron.sana);
}, 0);Konsolda (Chrome 154, Live Server'da asosiy.js fayli):
Uncaught TypeError: Cannot read properties of null (reading 'sana')
http://127.0.0.1:5500/asosiy.js 9 20
true
Uncaught TypeError: Cannot read properties of null (reading 'sana')message— matn. Chrome'da uUncaughtbilan boshlanadi.filename,lineno,colno— xato qaysi faylning nechanchi qatori, nechanchi ustunida.error—Errorobyektining o'zi,stack(stack trace) bilan (Stack trace). Qayd qilishda eng foydalisi shu.
Oxirgi qator — brauzerning o'z xabari, tinglovchidan keyin. Uni ham event.preventDefault() to'xtatadi.
Eski kodlarda xuddi shu tinglovchining boshqa shaklini uchratasiz — window.onerror xususiyati:
window.onerror = (xabar, fayl, qator, ustun, xato) => {
console.log("onerror:", xabar, qator, ustun);
return true;
};Ikki farqi bor. Birinchidan, u event emas, beshta alohida argument oladi. Ikkinchidan, return true — preventDefault() ning o'rnini bosadi. Bu xususiyatga faqat bitta funksiya yoziladi — boshqa kutubxona ham window.onerror = ... yozsa, sizniki o'chib ketadi. Shuning uchun yangi kodda — addEventListener.
3.6 Uchta nozik holat
Boshqa domendagi skript. Xato boshqa domendan yuklangan skriptda bo'lsa (masalan CDN'dagi kutubxona), brauzer xavfsizlik uchun tafsilotlarni yashiradi: message — faqat Script error., fayl va qator yo'q. Tafsilot kerak bo'lsa — <script crossorigin src="..."> va server tomonda CORS ruxsati. CORS'ni CORS mijoz tomondan darsida o'rganamiz.
Yuklanmagan rasm yoki skript. <img> yoki <script> yuklanmasa, ularda ham error hodisasi chiqadi, lekin u window gacha ko'tarilmaydi (bubble qilmaydi). Uni ushlash uchun tinglovchini capture bosqichida ulang (Hodisa tarqalishi):
window.addEventListener("error", (event) => {
if (event.target !== window) {
console.log("Yuklanmadi:", event.target.tagName);
}
}, true);Uchinchi argument true — capture. Bu holda event — ErrorEvent emas, oddiy Event: message yo'q, nima yuklanmagani event.target da.
Kech ulangan catch. Promise rad etilib, "ushlanmagan" deb e'lon qilingandan keyin unga catch ulansa, brauzer rejectionhandled hodisasini chiqaradi — "u baribir ushlandi". Lekin bunga tayanmang: Node'da dastur bu paytgacha allaqachon to'xtagan bo'ladi.
Tekshirib ko'ring: Global
unhandledrejectiontinglovchisi bor. UbronlarniYukla()xatosini ushladi va foydalanuvchiga xabar ko'rsatdi. Bron saqlandimi?
Javob
Yo'q. Tinglovchi xato sodir bo'lgandan keyin ishlaydi: bronlarniYukla allaqachon to'xtagan va uning ishi bajarilmagan. Global tinglovchi xatoni ko'radi va xabar beradi, lekin ishni qayta bajarmaydi va tuzatmaydi. Ishni qutqarish — joyidagi try/catch ning vazifasi.
4. Node: dastur to'xtaydi
4.1 Brauzerdan katta farq
Node'da ushlanmagan xato butun dasturni to'xtatadi. Server kodida bu — hamma foydalanuvchilar uchun to'xtash:
console.log("Server ishga tushdi");
Promise.reject(new Error("Baza bilan aloqa yo'q"));
setTimeout(() => console.log("Bu chiqmaydi"), 100);Konsolda (Node 24):
Server ishga tushdi
file:///.../server.mjs:2
Promise.reject(new Error("Baza bilan aloqa yo'q"));
^
Error: Baza bilan aloqa yo'q
at file:///.../server.mjs:2:16
Node.js v24.21.0Node xatoni stack trace bilan chiqardi va 1-kod bilan tugadi (1 — "xato bilan tugadi"; 0 — "muvaffaqiyatli"). 100 ms li taymer ishlamadi. Sinxron throw (masalan taymer ichida) ham xuddi shunday tugaydi.
Nega Node bunchalik qattiq? Node 15 dan oldin ushlanmagan rad etilish faqat ogohlantirish bilan o'tib ketardi. Natijada serverlar "yarim tirik" holatda ishlab, xatolar oylab sezilmasdi. Endi qoida: ushlanmagan xato — halokat. Xohlasangiz, node --unhandled-rejections=warn server.mjs bilan eski xulqni qaytarish mumkin, lekin buni qilmang.
Sabab satr bo'lsa (Promise.reject("Tarmoq yo'q")), Node uzunroq tushuntirish beradi:
UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Tarmoq yo'q".Tarjimasi: "Bu xato yo catch bloki bo'lmagan async funksiya ichida tashlangan, yo .catch() bilan ushlanmagan Promise rad etilganidan kelib chiqqan. Promise "Tarmoq yo'q" sababi bilan rad etildi". Ya'ni Node ikkala ehtimoliy sababni ham aytadi. Satrda stack trace yo'q — shuning uchun doim new Error(...) bilan rad eting.
4.2 process.on: oxirgi chiziq Node'da
process — Node'ning global obyekti, joriy dastur haqida (process obyekti darsida to'liq). Uning on metodi brauzerdagi addEventListener ga o'xshaydi. Ikki hodisa bizga kerak:
process.on("unhandledRejection", (sabab) => {
console.log("unhandledRejection:", sabab.message);
});
process.on("uncaughtException", (xato, manba) => {
console.log("uncaughtException:", xato.message, `(${manba})`);
});
Promise.reject(new Error("Baza bilan aloqa yo'q"));
setTimeout(() => {
throw new Error("Taymerda xato");
}, 0);
setTimeout(() => console.log("Dastur hali ishlayapti"), 50);Konsolda:
unhandledRejection: Baza bilan aloqa yo'q
uncaughtException: Taymerda xato (uncaughtException)
Dastur hali ishlayaptiunhandledRejection— brauzerdagiunhandledrejectionning egizagi (yozilishiga qarang: Node'da kattaR). Tinglovchi sabab va Promise'ni oladi.uncaughtException— brauzerdagierrorning egizagi. Ikkinchi argumentmanba— xato qayerdan kelgani.
Tinglovchi bor ekan, Node dasturni to'xtatmadi — oxirgi qatorga qarang. Bu esa yangi xavf tug'diradi.
Yana bir nozik joy: faqat uncaughtException tinglovchisi bo'lsa, ushlanmagan rad etilish ham unga keladi, manba esa unhandledRejection bo'ladi. Node rad etilishni avval "xatoga aylantiradi", keyin oddiy ushlanmagan xato kabi uzatadi.
4.3 Qayd qiling — va to'xtating
Node hujjatlari aniq aytadi: uncaughtException dan keyin dasturni davom ettirmang. Xato funksiyaning o'rtasida sodir bo'ldi. Ochilgan fayl yopilmagan, bazadagi tranzaksiya (bir nechta o'zgarishni "hammasi yoki hech biri" qilib saqlash) yarim yo'lda qolgan, xotiradagi holat chala o'zgargan bo'lishi mumkin. Bunday "yarim tirik" server keyingi so'rovlarda g'alati xatolar beradi — eng yomoni, noto'g'ri ma'lumot saqlaydi.
To'g'ri naqsh — qayd qil, keyin chiq:
process.on("uncaughtException", (xato, manba) => {
console.error(`Halokatli xato (${manba}):`, xato.message);
process.exit(1);
});
console.log("Server ishga tushdi");
Promise.reject(new Error("Baza bilan aloqa yo'q"));
setTimeout(() => console.log("Bu chiqmaydi"), 100);Konsolda:
Server ishga tushdi
Halokatli xato (unhandledRejection): Baza bilan aloqa yo'qBu yerda nima bo'ladi:
- Faqat
uncaughtExceptiontinglovchisi bor. Shuning uchun rad etilish ham unga keldi —manbabuni aytib turibdi. Ikkala yo'l bitta joyga yig'ildi. - Tinglovchi xatoni qayd qildi.
console.error—console.logning xatolar uchun varianti: matn xatolar oqimiga (stderr) yoziladi va log yig'uvchi vositalar uni alohida ajratadi. process.exit(1)— dasturni darhol to'xtatadi.1— "xato bilan tugadi" kodi. Taymer ishlamadi.
Serverlarda dasturni qayta ishga tushiradigan nazoratchi bo'ladi (Docker, PM2, systemd — serverda dasturlarni boshqaradigan vositalar; keyingi qismlarda, hozir bilish shart emas). U yiqilgan jarayonni bir soniyada qaytadan yoqadi — toza holat bilan. Bu mavzu: Process darajasidagi xatolar va crash strategiyasi.
Tekshirib ko'ring: Nega brauzerda xatodan keyin sahifa ishlashda davom etadi, Node'da esa dastur to'xtashi kerak?
Javob
Brauzerda har task alohida: xato bitta tinglovchini buzadi, lekin sahifa — bitta foydalanuvchi uchun — boshqa tugmalar bilan ishlashi mumkin, va foydalanuvchi uni xohlagan payt yangilaydi. Node server esa minglab foydalanuvchiga xizmat qiladigan bitta jarayon: buzilgan holat hammaga tegadi. Toza qayta ishga tushirish "yarim tirik" ishlashdan xavfsizroq.
5. Xatolarni qayd etish (loglash)
5.1 Nimani yozish kerak
Konsoldagi xabar faqat sizning kompyuteringizda ko'rinadi. Jasur akaning saytida esa xato mehmonning telefonida bo'ladi. Uni bilish uchun xato haqidagi ma'lumot serverga yuborilishi kerak. Buni xatolarni qayd etish yoki loglash (logging) deyishadi.
Foydali qayd yozuvida beshta narsa bo'ladi:
| Maydon | Nima uchun |
|---|---|
nom, xabar |
xato turi va matni |
stek |
qaysi funksiya, qaysi qator |
manba |
error yoki unhandledrejection |
sahifa, vaqt |
qayerda va qachon |
Har global tinglovchidan bitta funksiyani chaqiramiz. U har xil sababni (Error, satr, obyekt) bir xil yozuvga aylantiradi:
function qaydYasa(sabab, manba) {
const xatomi = sabab instanceof Error;
return {
nom: xatomi ? sabab.name : typeof sabab,
xabar: xatomi ? sabab.message : String(sabab),
stekBor: xatomi,
manba,
};
}
const xato = new TypeError("sana yo'q");
console.log(qaydYasa(xato, "unhandledrejection"));
console.log(qaydYasa("Tarmoq yo'q", "unhandledrejection"));Konsolda:
{
nom: 'TypeError',
xabar: "sana yo'q",
stekBor: true,
manba: 'unhandledrejection'
}
{
nom: 'string',
xabar: "Tarmoq yo'q",
stekBor: false,
manba: 'unhandledrejection'
}Haqiqiy kodda stekBor o'rniga stek: sabab.stack — butun stack trace matni yoziladi. Bu yerda faqat bor-yo'qligini oldik: stack trace'da fayl yo'li bor va u har kompyuterda har xil. Brauzerda yana sahifa: location.href va vaqt: new Date().toISOString() qo'shiladi (Date — 12-qismda).
5.2 Yuborish va cheklash
Yozuv tayyor bo'lgach, uni serverga yuborasiz. Brauzerda buning uchun maxsus kichik so'rov bor — navigator.sendBeacon(url, matn): sahifa yopilayotganda ham yetib boradi. Serverga so'rov yuborishni fetch bilan ma'lumot yuborish darsida o'rganamiz.
Ikki himoya qoidasi:
- Takrorlarni birlashtiring. Sikl ichidagi xato sekundiga yuz marta chiqishi mumkin. Har birini yuborish — serverni ko'mib tashlash. Bir xil
xabarni bir marta yuboring va sanab boring. - Chegara qo'ying. Bitta sahifada, masalan, ko'pi bilan 10 ta yozuv. Undan keyin — jim.
Buni 3-mashqda yozasiz.
5.3 Tayyor xizmatlar
Real loyihalarda bu ishni o'zingiz yozmaysiz. Sentry kabi xizmatlar o'z kutubxonasini sahifaga ulaydi. Kutubxona error va unhandledrejection ni tinglaydi, stack trace'ni yig'adi va xatolarni guruhlab, dasturchiga xabar yuboradi: "bugun 37 foydalanuvchida Cannot read properties of undefined (reading 'sana')". Ichida — bugungi darsdagi aynan shu ikki hodisa. Ulashni Xatolarni kuzatish: Sentry frontendda darsida qilamiz — hozir bilish shart emas.
Diqqat: Logga shaxsiy ma'lumot tushmasin. Xato xabarida yoki
sahifamanzilida mehmonning telefoni, paroli, tokeni bo'lishi mumkin (?tel=+998...). Log — boshqa odamlar ham o'qiydigan joy. Yuborishdan oldin bunday maydonlarni olib tashlang.
6. Hujumchi nigohi
Xato xabari ikki tomonga xizmat qiladi: dasturchiga ham, hujumchiga ham.
Hujum. Hujumchi formaga ataylab g'alati qiymatlar yuboradi: juda uzun ism, ' belgisi, manfiy son. Keyin ekrandagi xatoni o'qiydi. Agar sayt xato.stack yoki server xatosini to'g'ridan-to'g'ri ko'rsatsa, hujumchi fayl yo'llarini, kutubxona versiyalarini, ba'zan baza so'rovining bir qismini ko'radi. Bu — keyingi hujum uchun xarita.
Himoya. Bugungi kod bunga qarshi turadi:
- Foydalanuvchiga — faqat umumiy, tushunarli xabar ("Nimadir noto'g'ri ketdi..."). Tafsilot — faqat logga.
textContentbilan chiqariladi — xabar ichidagi HTML bajarilmaydi (Kontentni o'zgartirish va XSS xavfi).- Log takrorlari birlashtiriladi va cheklanadi — hujumchi bir xil xatoni ming marta chiqarib, log xizmatini to'ldira olmaydi.
7. Ko'p uchraydigan xatolar
7.1 Global tinglovchini catch o'rniga ishlatish
"Hamma xatoni bitta joyda ushlayman" — keyin hech qayerda try/catch yo'q. Natija: har xato funksiyani to'xtatadi va foydalanuvchi umumiy "Nimadir noto'g'ri" ni ko'radi — internet uzilganda ham, sana noto'g'ri bo'lganda ham. Tuzatish: kutilgan xatolar joyida, aniq xabar bilan; global — faqat kutilmaganlar uchun.
7.2 await siz try
«try/catch nega ushlamadi» bo'limidagi tuzoq: try { bronniSaqla(); } — async funksiya chaqirilgan, lekin kutilmagan. Shu oilada yana biri — return va return await farqi:
async function bronQil() {
try {
return bronniSaqla(); // ❌ rad etilish try'dan qochib ketadi
} catch (xato) {
console.log("Ushlanmaydi");
}
}return bronniSaqla() Promise'ni kutmasdan qaytaradi — rad etilish chaqiruvchiga o'tadi. Tuzatish: try ichida return await bronniSaqla().
7.3 uncaughtException dan keyin davom etish
process.on("uncaughtException", (x) => console.log(x)) — va server "ishlab" turaveradi. Holati buzilgan. Tuzatish: qayd qiling va jarayonni to'xtating; qayta ishga tushirishni nazoratchiga topshiring.
7.4 Tinglovchi ichidagi xato
Global tinglovchining o'zi xato bersa (masalan event.reason.message, reason esa satr bo'lsa) — u ham ushlanmagan xato bo'ladi. Ba'zan bu cheksiz zanjirga aylanadi: xato → tinglovchi → yana xato. Tuzatish: tinglovchida instanceof Error bilan tekshiring va ichini oddiy, ishonchli qiling.
7.5 Har doim preventDefault()
Konsol "toza" bo'lsin deb hamma xatoni jimitish — DevTools'da hech narsa ko'rinmaydi, xatolar faqat log xizmatida qoladi (agar u ishlasa). Tuzatish: brauzerning xabarini qoldiring.
8. Mashqlar
1-mashq (oson): Ushlanadimi?
Har holat uchun ayting: catch ushlaydimi yoki konsolda Uncaught chiqadimi? kut — oldingi darslardagi yordamchi.
try { JSON.parse("{"); } catch (x) { ... }try { setTimeout(() => JSON.parse("{"), 0); } catch (x) { ... }async function f() { try { await kut(100); JSON.parse("{"); } catch (x) { ... } }Promise.reject(new Error("A")).then(() => console.log("ok"));
Yechim
- Ushlanadi — xato
tryichida, sinxron. - Uncaught —
tryfaqat taymerni qo'ydi va tugadi; xato keyinroq, boshqa task'da chiqadi (Uncaught SyntaxError: ...). - Ushlanadi —
awaitdan keyingi kod ham shutryichida.asyncfunksiya ichidagitry/catchawaitlar bo'ylab "cho'ziladi". - Uncaught (in promise) —
thenfaqat muvaffaqiyatni ushlaydi. Rad etilish zanjir bo'ylab o'tib ketadi va oxirida hech kim yo'q (Promise zanjiri).
2-mashq (o'rta): Bir martalik ogohlantirish
«Bahor» sahifasidagi ogohlantirish har xatoda qayta-qayta "yonib" turmasin. Global tinglovchi yozing:
- Birinchi kutilmagan xatoda —
#ogohlantirishelementida xabar chiqsin. - Har xatoda
#sonielementidagi hisob bittaga oshsin ("Xatolar: 2"). reasonsatr bo'lsa ham tinglovchi o'zi xato bermasin.
Sinov uchun sahifa yuklanganda ikkita rad etilish va bitta sinxron xato chiqaring. Xatoni taymer ichidan tashlang, aks holda u sizning skriptingizni to'xtatadi.
Yechim
<p id="ogohlantirish" role="alert" hidden></p>
<p id="soni">Xatolar: 0</p>
<script>
const ogohlantirish = document.getElementById("ogohlantirish");
const soniEl = document.getElementById("soni");
let soni = 0;
function xatoniQaydEt() {
soni++;
soniEl.textContent = `Xatolar: ${soni}`;
if (ogohlantirish.hidden) {
ogohlantirish.textContent = "Nimadir noto'g'ri ketdi.";
ogohlantirish.hidden = false;
}
}
window.addEventListener("error", xatoniQaydEt);
window.addEventListener("unhandledrejection", xatoniQaydEt);
Promise.reject(new Error("Menyu yuklanmadi"));
Promise.reject(new Error("Tarmoq yo'q"));
setTimeout(() => {
throw new Error("Taymerda xato");
}, 50);
</script>Konsolda:
Uncaught (in promise) Error: Menyu yuklanmadi
Uncaught (in promise) Error: Tarmoq yo'q
Uncaught Error: Taymerda xatoSahifada "Xatolar: 3" va bitta ogohlantirish. xatoniQaydEt event ni umuman o'qimaydi — shuning uchun reason satr bo'lsa ham xato bermaydi. ogohlantirish.hidden tekshiruvi — "faqat birinchi marta". Konsoldagi uchta qizil qator — brauzerning o'z xabarlari: biz preventDefault() chaqirmadik.
3-mashq (qiyin): Xato kuzatuvchi
Node'da xatoKuzatuvchiYarat(chegara) funksiyasini yozing. U ikki metodli obyekt qaytarsin:
qaydEt(sabab, manba)— yozuv qo'shadi. Bir xilxabarli xato qayta kelsa, yangi yozuv emas, mavjudiningsonioshadi. Har xil xabarlar sonichegaraga yetgach, yangilari e'tiborsiz qoladi.hisobot()— yozuvlar massivi ({ xabar, manba, soni }).
Uni process.on("unhandledRejection", ...) ga ulang va sinang: chegara = 2, to'rtta rad etilish — "Baza yo'q" ikki marta, "Kesh yo'q" va "Disk to'ldi" bir martadan. 100 ms dan keyin hisobotni chiqaring. Ishora: holatni closure'da saqlang (Closure amaliyotda), qidirish uchun find (HOF metodlari). Faylni kurs/mashqlar/11/14-xatolar/kuzatuvchi.mjs ga saqlang.
Yechim
function xatoKuzatuvchiYarat(chegara) {
const yozuvlar = [];
function qaydEt(sabab, manba) {
const xabar =
sabab instanceof Error ? sabab.message : String(sabab);
const bor = yozuvlar.find((y) => y.xabar === xabar);
if (bor) {
bor.soni++;
return;
}
if (yozuvlar.length >= chegara) {
return;
}
yozuvlar.push({ xabar, manba, soni: 1 });
}
function hisobot() {
return yozuvlar.map((y) => ({ ...y }));
}
return { qaydEt, hisobot };
}
const kuzatuvchi = xatoKuzatuvchiYarat(2);
process.on("unhandledRejection", (sabab) => {
kuzatuvchi.qaydEt(sabab, "unhandledRejection");
});
Promise.reject(new Error("Baza yo'q"));
Promise.reject(new Error("Kesh yo'q"));
Promise.reject(new Error("Baza yo'q"));
Promise.reject(new Error("Disk to'ldi"));
setTimeout(() => console.log(kuzatuvchi.hisobot()), 100);Konsolda:
[
{ xabar: "Baza yo'q", manba: 'unhandledRejection', soni: 2 },
{ xabar: "Kesh yo'q", manba: 'unhandledRejection', soni: 1 }
]"Disk to'ldi" yozilmadi — chegara 2 ga yetgan edi. Haqiqiy loyihada chegara 10–50, hisobot() esa serverga yuboriladi. hisobot nusxa qaytaradi ({ ...y }) — tashqi kod soni ni o'zgartira olmasin (Immutable yangilash).
Muhim: bu yechimda dastur xatolardan keyin to'xtamaydi — mashq uchun shunday. Server kodida esa «Qayd qiling — va to'xtating» bo'limidagi naqsh bilan birga ishlating.
git add 11/14-xatolar/kuzatuvchi.mjs
git commit -m "11/14: takrorlarni birlashtiradigan xato kuzatuvchi"9. Real ishda
- Xatolarni kuzatish xizmatlari. Sentry, Bugsnag, Datadog — deyarli har jiddiy saytda bor. Ichida —
errorvaunhandledrejectiontinglovchilari. O'zbekistondagi katta ilovalar (to'lov, yetkazib berish) ham xatolarni shunday kuzatadi: foydalanuvchi shikoyat qilishidan oldin jamoa xabar oladi. - Freymvorklar. React'dagi "Error Boundary" — komponent ichidagi xatolar uchun shu g'oyaning o'zi: buzilgan qism o'rniga zaxira ekran (React — 17-qismda). Node freymvorklarida — global xato middleware'i (har so'rov o'tadigan umumiy "xato ushlagich" funksiya; Node server darslarida).
- Serverlar.
process.on("uncaughtException")→ log → chiqish → Docker yoki PM2 qayta yoqadi. Bu — backend'dagi standart naqsh. - Intervyu. "Ushlanmagan Promise rad etilishi bilan Node nima qiladi?", "
try/catchasinxron xatoni qachon ushlaydi?", "uncaughtExceptiondan keyin nega davom etmaslik kerak?"
Xulosa
- Hech kim ushlamagan xato —
Uncaught ...; ushlanmagan rad etilish —Uncaught (in promise) .... - Brauzer faqat joriy task'ni to'xtatadi, sahifa ishlayveradi. Node esa butun dasturni to'xtatadi.
- Brauzerda oxirgi chiziq —
windowdagierrorvaunhandledrejection;preventDefault()konsol xabarini o'chiradi. - Node'da —
process.on("uncaughtException")va"unhandledRejection"; ulardan keyin qayd qiling va jarayonni to'xtating. - Global tinglovchi
catcho'rnini bosmaydi: u ishni qutqarmaydi, faqat xabar beradi va qayd qiladi. - Logga: xabar, stek, manba, sahifa, vaqt; takrorlarni birlashtiring, shaxsiy ma'lumotni olib tashlang.
Keyingi dars: Asinxron naqshlar — xatoga javob berish naqshlari: qayta urinish (retry) va eksponensial kutish, timeout, parallellik cheklovi va "oxirgi so'rov yutadi" muammosi.
Manbalar
- HTML Living Standard: "Runtime script errors", "Unhandled promise rejections" (
PromiseRejectionEvent,rejectionhandled) — html.spec.whatwg.org - MDN: "Window: error event", "Window: unhandledrejection event", "Window: rejectionhandled event" — developer.mozilla.org
- Node.js 24 hujjatlari: "Process — Event: 'uncaughtException'", "Warning: Using 'uncaughtException' correctly", "--unhandled-rejections" — nodejs.org/api/process.html
- Chrome 154 va Node 24.21 — darsdagi xabar matnlari shu versiyalarda olingan
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!