- Daxili xəta tiplərini (
TypeError,ReferenceError,RangeError,SyntaxError) və onların adi səbəblərini tanımaq - Öz xəta siniflərini yaratmaq,
causeəlavə etmək və xətaları, o cümlədən asinxron kodda, tipinə görə emal etmək - Stek izini oxumaq və kəsmə nöqtələri,
debuggervə konsol metodları ilə sazlama aparmaq
İstifadəçi yazır: «Düymə heç nə etmir». Ekranda heç bir işarə yoxdur, amma konsolda qırmızı sətir var: Chrome-da TypeError: Cannot read properties of undefined (reading 'price') və altında fayl adları ilə rəqəmlər. Yeni başlayan üçün bu, səs-küydür, peşəkar üçün isə birbaşa səhvin yerini göstərən xəritə. Bu dərsdə həmin xəritəni oxumağı və öz xətalarını düzgün qurmağı öyrənəcəksən.
Daxili xəta tipləri
| Tip | Adi səbəb | Nümunə |
|---|---|---|
TypeError | yanlış tipli qiymətlə əməliyyat: funksiya olmayanı çağırmaq, undefined/null-un xassəsini oxumaq | null.name, (42)() |
ReferenceError | mövcud olmayan (və ya TDZ-də olan) dəyişən | console.log(missing) |
RangeError | icazə verilən aralıqdan kənar ədəd | new Array(-1) |
SyntaxError | oxuna bilməyən kod və ya JSON | JSON.parse('{bad}') |
const attempts = [
() => null.name,
() => missingVariable,
() => new Array(-1),
() => JSON.parse('{bad json}'),
() => (42)(),
];
for (const attempt of attempts) {
try {
attempt();
} catch (error) {
console.log(error.name, '|', error instanceof Error);
}
}▸ Gözlənilən nəticə
TypeError | true ReferenceError | true RangeError | true SyntaxError | true TypeError | true
Öz xətaların və cause
throw istənilən qiyməti ata bilər, amma həmişə Error obyekti at — stek izi yalnız onda olur. Yaxşı qayda: yalnız emal edə bildiyin xətanı tut, qalanını yenidən at (throw error). Proqramın müxtəlif xətalarını ayırmaq üçün Error-dan irs alan siniflər ierarxiyası qur — onda instanceof ilə hər növə uyğun reaksiya vermək olur.
class AppError extends Error {
constructor(message, options) {
super(message, options);
this.name = this.constructor.name;
}
}
class ValidationError extends AppError {}
class NotFoundError extends AppError {}
function findUser(users, id) {
if (!Number.isInteger(id)) throw new ValidationError(`Bad id: ${id}`);
const user = users.find((u) => u.id === id);
if (!user) throw new NotFoundError(`User ${id} not found`);
return user;
}
const users = [{ id: 1, name: 'Aysel' }];
for (const id of [1, 'x', 7]) {
try {
console.log(findUser(users, id).name);
} catch (error) {
if (error instanceof ValidationError) console.log('400', error.message);
else if (error instanceof NotFoundError) console.log('404', error.message);
else throw error;
}
}▸ Gözlənilən nəticə
Aysel 400 Bad id: x 404 User 7 not found
this.constructor.name hər alt sinfə avtomatik düzgün ad verir. 400 və 404 — HTTP status kodlarıdır, API dərsində onlara qayıdacağıq.Aşağı səviyyəli xətanı tutub daha anlaşıqlı xəta atırsansa, orijinalı **cause** (ES2022) xassəsində saxla. Beləliklə, istifadəçiyə aydın mesaj göstərirsən, proqramçı isə əsl səbəbi itirmir.
function loadSettings(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new Error('Settings file is broken', { cause: error });
}
}
try {
loadSettings('{ theme: dark }');
} catch (error) {
console.log(error.message);
console.log('Caused by:', error.cause.name);
console.log(error.cause instanceof SyntaxError);
}▸ Gözlənilən nəticə
Settings file is broken Caused by: SyntaxError true
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function saveScore(score) {
await wait(100);
if (score < 0) throw new RangeError('Score cannot be negative');
return 'saved';
}
try {
console.log(await saveScore(10));
console.log(await saveScore(-5));
} catch (error) {
console.log(`${error.name}: ${error.message}`);
}
const result = await saveScore(-1).catch((error) => `fallback (${error.message})`);
console.log(result);▸ Gözlənilən nəticə
saved RangeError: Score cannot be negative fallback (Score cannot be negative)
Stek izini oxumaq
Stek izi (stack trace) xəta yarananda çağırışlar zəncirini göstərir, ən yenisi yuxarıda. Birinci sətir xətanın adı və mesajıdır, sonrakı sətirlər isə at funksiya (fayl:sətir:sütun) şəklindədir. Aşağıdakı cart.js faylında ikinci məhsulun product xassəsi yoxdur. Node.js-in çap etdiyi iz (qovluq yolları qısaldılıb, Node-un daxili sətirləri buraxılıb):
// cart.js
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.product.price * item.qty, 0);
}
function renderCart(cart) {
return calculateTotal(cart.items);
}
renderCart({ items: [{ product: { price: 2 }, qty: 1 }, { qty: 3 }] });TypeError: Cannot read properties of undefined (reading 'price')
at cart.js:3:57
at Array.reduce (<anonymous>)
at calculateTotal (cart.js:3:16)
at renderCart (cart.js:6:10)
at Object.<anonymous> (cart.js:8:1)Sazlama alətləri
- 1Səhvi təkrarla
Səhvə gətirib çıxaran dəqiq addımları tap.
- 2Kəsmə nöqtəsi qoy
DevTools ›
Sourcespanelində sətir nömrəsinə klik et və ya kodadebugger;yaz — DevTools açıq olanda icra orada dayanacaq. - 3Qiymətlərə bax
Scopebölməsində dəyişənlərə bax, siçanı qiymətin üstünə gətir,Watch-a ifadə əlavə et. - 4Addım-addım get
Sətir-sətir irəlilə, funksiyanın içinə gir və ya ondan çıx.
- 5Düzəlt və yoxla
Düzəlişdən sonra eyni addımları yenidən keç.
Konsolda log-dan başqa faydalı metodlar da var. Bu səhifədəki icraçı yalnız console.log-u göstərir, ona görə nümunəni brauzer konsolunda və ya Node.js-də işə sal. Aşağıdakı nəticə Node.js-dəndir; sort üçün ölçülən vaxt hər dəfə fərqli olur.
const students = [
{ name: 'Aysel', score: 92 },
{ name: 'Murad', score: 78 },
];
console.table(students);
console.group('Checkout');
console.log('items: 3');
console.warn('coupon expired');
console.groupEnd();
console.count('click');
console.count('click');
console.assert(students.length > 5, 'Expected more than 5 students');
console.time('sort');
students.sort((a, b) => b.score - a.score);
console.timeEnd('sort');┌─────────┬─────────┬───────┐ │ (index) │ name │ score │ ├─────────┼─────────┼───────┤ │ 0 │ 'Aysel' │ 92 │ │ 1 │ 'Murad' │ 78 │ └─────────┴─────────┴───────┘ Checkout items: 3 coupon expired click: 1 click: 2 Assertion failed: Expected more than 5 students sort: 0.027ms
ValidationError sinfini tamamla (name 'ValidationError' olsun) və parseAge(text) funksiyasını yaz. Mətn tam ədəd deyilsə, Not a whole number: <text>, 0–120 aralığından kənardırsa, Out of range: <age> mesajlı ValidationError at, əks halda yaşı qaytar.
class ValidationError extends Error {
// set this.name in the constructor
}
function parseAge(text) {
// Number(text) must be an integer from 0 to 120
}
for (const input of ['16', 'abc', '130', '42']) {
try {
console.log('Age:', parseAge(input));
} catch (error) {
if (error instanceof ValidationError) {
console.log(`${error.name}: ${error.message}`);
} else {
throw error;
}
}
}▸ Gözlənilən nəticə
Age: 16 ValidationError: Not a whole number: abc ValidationError: Out of range: 130 Age: 42
retry(fn, times) funksiyasını yaz: fn-i uğur qazanana qədər ən çoxu times dəfə çağırsın və hər uğursuzluqda Retrying after: <mesaj> çap etsin. Bütün cəhdlər uğursuz olsa, sonuncu xətanı cause-da saxlayan All <times> attempts failed mesajlı xəta atsın.
function createFlakyTask(failuresBeforeSuccess) {
let calls = 0;
return () => {
calls++;
if (calls <= failuresBeforeSuccess) throw new Error(`Attempt ${calls} failed`);
return `Success on attempt ${calls}`;
};
}
function retry(fn, times) {
// your code here
}
console.log(retry(createFlakyTask(2), 3));
try {
retry(createFlakyTask(5), 3);
} catch (error) {
console.log(error.message, '| cause:', error.cause.message);
}▸ Gözlənilən nəticə
Retrying after: Attempt 1 failed Retrying after: Attempt 2 failed Success on attempt 3 Retrying after: Attempt 1 failed Retrying after: Attempt 2 failed Retrying after: Attempt 3 failed All 3 attempts failed | cause: Attempt 3 failed
Əsas fikirlər
TypeError— yanlış tip və yaundefined,ReferenceError— naməlum dəyişən,RangeError— aralıqdan kənar qiymət,SyntaxError— oxunmayan kod və ya JSON.- Mesajın mətnini yox,
error.name-i və yainstanceof-u yoxla — mesajlar brauzerə görə dəyişir. - Öz xəta sinifləri və
causexətaları mənalı edir və orijinal səbəbi saxlayır. - Asinxron xəta yalnız
tryiçindəawaitvə ya.catch()ilə tutulur. - Stek izini öz faylının birinci sətrindən oxu; təxmin etmək əvəzinə kəsmə nöqtələri,
debuggervə konsol metodlarından istifadə et.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
const user = null; user.length; hansı xətanı verir?