Що містить стек викликів (stack trace)?
1. Що таке стек викликів
Стек викликів (call stack) - це структура даних, у якій JavaScript зберігає інформацію про те, які функції зараз виконуються і в якому порядку вони були викликані.
Коли виникає помилка, JS створює "знімок" цього стеку - так званий stack trace, який показує, де саме і в якій послідовності був викликаний код, що призвів до помилки.
2. Як виглядає стек викликів при помилці
Розглянемо приклад.
function a() {
b();
}
function b() {
c();
}
function c() {
throw new Error("Щось пішло не так!");
}
try {
a();
} catch (err) {
console.log(err.stack);
}Вивід у консолі:
Error: Щось пішло не так!
at c (<anonymous>:8:9)
at b (<anonymous>:4:3)
at a (<anonymous>:1:3)
at <anonymous>:12:33. Що міститься в stack trace
Кожен рядок у stack - це один рівень виклику функції
(знизу вгору: від місця виникнення помилки до найвищої функції, яка запустила ланцюжок).
Розберемо:
Error: Щось пішло не так! ← тип помилки і повідомлення
at c (<anonymous>:8:9) ← функція c() викликала помилку
at b (<anonymous>:4:3) ← c() була викликана з b()
at a (<anonymous>:1:3) ← b() була викликана з a()
at <anonymous>:12:3 ← a() викликана в глобальній областіКожен рядок вказує:
- ім'я функції (
at c,at b,at a) - файл (або
<anonymous>, якщо без імені) - номер рядка і стовпця, де відбувся виклик
4. Де зберігається стек
Коли створюється об'єкт помилки (new Error()), у нього автоматично з'являється властивість .stack, яка містить:
- назву помилки (
Error,TypeErrorтощо) - повідомлення (
message) - трасування викликів (stack trace)
Приклад:
const err = new Error("Помилка мережі");
console.log(err.stack);Вивід:
Error: Помилка мережі
at <anonymous>:1:135. Як використовувати стек в обробці помилок
try {
throw new Error("Непередбачена помилка");
} catch (e) {
console.error("Помилка:", e.message);
console.error("Стек викликів:\n", e.stack);
}Вивід:
Помилка: Непередбачена помилка
Стек викликів:
Error: Непередбачена помилка
at <anonymous>:2:9
at ...6. Користувацькі помилки теж мають стек
Якщо ти створюєш свою помилку через class extends Error,
то властивість .stack у неї теж буде доступна.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
try {
throw new ValidationError("Невірний email");
} catch (e) {
console.log(e.stack);
}Вивід:
ValidationError: Невірний email
at <anonymous>:8:9
at ...7. Стек при асинхронних помилках
Асинхронні виклики (через setTimeout, Promise, await)
можуть "розірвати" стек, тому що вони виконуються пізніше - в іншій ітерації event loop.
Приклад:
function a() {
setTimeout(() => {
throw new Error("Помилка в таймері");
}, 0);
}
a();Вивід:
Uncaught Error: Помилка в таймері
at Timeout._onTimeout (<anonymous>:3:11)Тут видно лише частину стеку, тому що помилка сталася вже в іншому контексті виконання.
Підсумок
| Елемент | Що це означає |
|---|---|
Error.message | Текст помилки |
Error.name | Тип помилки (TypeError, ReferenceError, …) |
Error.stack | Повний шлях викликів до місця помилки |
Кожен at ... | Одна функція в ланцюжку викликів |
| Порядок | Зверху - місце помилки, нижче - хто її викликав |
Практичне застосування
- Швидко знаходити місце збою в коді;
- Розуміти, які функції викликали помилку;
- Зберігати
stack traceв логах (наприклад, у Sentry, GlitchTip, Logtail); - Робити trace-бекенд для аналізу помилок користувачів.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.