JS Tower
JavaScript & TypeScriptМодуль 6: ООП и паттерны

Обработка ошибок

try, catch, finally и создание ошибок

Цель урока

В этом уроке ты научишься:

  • Обрабатывать ошибки с try/catch
  • Создавать собственные ошибки
  • Правильно использовать finally

try...catch

try {
  let result = JSON.parse("invalid json");
} catch (error) {
  console.log("Ошибка:", error.message);
}

console.log("Код продолжает работать");

Объект Error

try {
  throw new Error("Что-то пошло не так");
} catch (error) {
  console.log(error.name);    // "Error"
  console.log(error.message); // "Что-то пошло не так"
  console.log(error.stack);   // стек вызовов
}

Типы ошибок

// SyntaxError — ошибка синтаксиса
// JSON.parse("invalid");

// ReferenceError — обращение к несуществующей переменной
// console.log(undefinedVar);

// TypeError — неверный тип
// null.toString();

// RangeError — выход за пределы
// new Array(-1);

Создание ошибок

throw

function divide(a, b) {
  if (b === 0) {
    throw new Error("Деление на ноль");
  }
  return a / b;
}

try {
  console.log(divide(10, 0));
} catch (error) {
  console.log(error.message); // "Деление на ноль"
}

Пользовательские ошибки

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

class HttpError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = "HttpError";
    this.statusCode = statusCode;
  }
}

function validateEmail(email) {
  if (!email.includes("@")) {
    throw new ValidationError("Неверный email");
  }
}

try {
  validateEmail("invalid");
} catch (error) {
  if (error instanceof ValidationError) {
    console.log("Ошибка валидации:", error.message);
  } else {
    throw error; // пробрасываем неизвестные ошибки
  }
}

finally

Выполняется всегда, независимо от результата:

function readFile() {
  let file = openFile("data.txt");
  
  try {
    let data = file.read();
    return data;
  } catch (error) {
    console.log("Ошибка чтения");
    return null;
  } finally {
    file.close(); // Выполнится в любом случае
  }
}

Обработка в async/await

async function fetchData() {
  try {
    let response = await fetch("/api/data");
    
    if (!response.ok) {
      throw new HttpError("Ошибка HTTP", response.status);
    }
    
    return await response.json();
  } catch (error) {
    if (error instanceof HttpError) {
      console.log(`HTTP ${error.statusCode}: ${error.message}`);
    } else {
      console.log("Сетевая ошибка:", error.message);
    }
    return null;
  }
}

Глобальная обработка

// В браузере
window.onerror = function(message, source, line, col, error) {
  console.log("Глобальная ошибка:", message);
};

// Необработанные промисы
window.onunhandledrejection = function(event) {
  console.log("Необработанный промис:", event.reason);
};

Практика

Задание 1: Базовая обработка

Задача: Обработай ошибку парсинга JSON.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Ошибка парсинга

Задание 2: Пользовательская ошибка

Задача: Создай и выброси свою ошибку.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
ValidationError: Неверный возраст

Задание 3: finally

Задача: Используй finally для очистки.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Ошибка
Завершено

Проверь себя

  1. Когда выполняется finally?
  2. Как создать свой тип ошибки?
  3. Как проверить тип ошибки?