Мониторинг ошибок

Haunted — это современная библиотека для создания веб-компонентов на базе реактивного подхода, построенного поверх Web Components и Hooks, аналогичных React. Одной из критически важных задач при разработке сложных приложений является управление и мониторинг ошибок, как на уровне компонентов, так и в глобальном контексте. Haunted предоставляет гибкие инструменты для обработки исключений, предотвращения неконтролируемого падения приложения и ведения логов.


Обработка ошибок на уровне компонента

В Haunted нет встроенного механизма componentDidCatch, как в React, но ошибки можно перехватывать через try/catch внутри функций эффектов (useEffect) и других хуков. Это позволяет контролировать поведение компонента при возникновении исключений и выполнять необходимые действия, например, логирование или отображение fallback UI.

import { html, component, useEffect } from 'haunted';

function ErrorProneComponent() {
  useEffect(() => {
    try {
      riskyOperation();
    } catch (error) {
      console.error('Ошибка в компоненте:', error);
      // Можно задать локальное состояние для отображения сообщения
    }
  }, []);

  return html`<div>Компонент с потенциальной ошибкой</div>`;
}

customElements.define('error-prone-component', component(ErrorProneComponent));

Ключевой момент: все операции, которые могут вызвать исключение, рекомендуется оборачивать в блоки try/catch внутри эффектов или хуков. Это предотвращает остановку реактивного цикла Haunted и сохраняет работоспособность остальной части приложения.


Создание глобального обработчика ошибок

Для комплексного мониторинга ошибок часто требуется глобальный уровень контроля. В браузере это реализуется через события window.onerror и window.onunhandledrejection, которые перехватывают ошибки синхронного и асинхронного кода соответственно.

window.oner ror = (message, source, lineno, colno, error) => {
  console.error('Глобальная ошибка:', { message, source, lineno, colno, error });
  // Можно отправлять данные на сервер мониторинга
  return true; // предотвращает всплытие ошибки в консоль браузера
};

window.onunhandledreject ion = (event) => {
  console.error('Необработанное обещание:', event.reason);
};

Использование этих обработчиков вместе с локальной обработкой в компонентах позволяет построить многоуровневую стратегию мониторинга.


Реактивное управление состоянием ошибок

Haunted поддерживает реактивное состояние через useState, что позволяет динамически изменять UI при возникновении ошибки. Это особенно полезно для отображения уведомлений, fallback-компонентов или индикаторов состояния.

import { html, component, useState } from 'haunted';

function ReactiveErrorComponent() {
  const [error, setError] = useState(null);

  const handleClick = () => {
    try {
      throw new Error('Имитированная ошибка');
    } catch (err) {
      setError(err.message);
    }
  };

  return html`
    <button @click=${handleClick}>Провоцировать ошибку</button>
    ${error ? html`<div class="error">Ошибка: ${error}</div>` : ''}
  `;
}

customElements.define('reactive-error-component', component(ReactiveErrorComponent));

Особенность: реактивное обновление состояния позволяет отображать ошибки без перезагрузки компонента и сохранять интерактивность интерфейса.


Логирование и интеграция с внешними сервисами

Для профессионального мониторинга в реальных проектах ошибки часто отправляются в аналитические и логирующие сервисы, такие как Sentry, LogRocket или собственные серверы. Haunted, как библиотека UI, не ограничивает возможность интеграции.

function logErrorToService(error) {
  fetch('/api/log', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ message: error.message, stack: error.stack })
  });
}

function ErrorComponent() {
  const [error, setError] = useState(null);

  useEffect(() => {
    try {
      riskyOperation();
    } catch (err) {
      setError(err);
      logErrorToService(err);
    }
  }, []);

  return html`${error ? html`<div>Произошла ошибка</div>` : html`<div>Всё работает</div>`}`;
}

Рекомендация: всегда включать отправку стека ошибок и дополнительной контекстной информации, чтобы облегчить диагностику в продакшене.


Предотвращение падения приложения

Основная цель мониторинга ошибок — не только логирование, но и предотвращение неконтролируемого падения. Стратегии включают:

  1. Fallback UI — отображение безопасного интерфейса вместо сломанного компонента.
  2. Гибкая архитектура компонентов — изоляция сложной логики в отдельных компонентах для минимизации влияния ошибок на остальную часть приложения.
  3. Тестирование критических участков — использование unit- и интеграционных тестов для проверки устойчивости к исключениям.
function SafeWrapper({ child }) {
  const [hasError, setHasError] = useState(false);

  try {
    return child();
  } catch (error) {
    setHasError(true);
    console.error('Ошибка внутри SafeWrapper:', error);
    return html`<div>Не удалось загрузить компонент</div>`;
  }
}

Асинхронные операции и ошибки

Haunted активно работает с асинхронными функциями через useEffect. Любые промисы, которые могут завершиться с ошибкой, должны быть корректно обработаны, иначе ошибка выйдет за пределы реактивного цикла.

useEffect(() => {
  async function fetchData() {
    try {
      const response = await fetch('/api/data');
      if (!response.ok) throw new Error('Сетевая ошибка');
      const data = await response.json();
      setData(data);
    } catch (err) {
      setError(err.message);
    }
  }

  fetchData();
}, []);

Важно: для асинхронных операций всегда использовать отдельные функции внутри useEffect и блоки try/catch. Это предотвращает неожиданные сбои и сохраняет отзывчивость интерфейса.


Стратегии интеграции мониторинга в Haunted-приложение

  • Локальные try/catch внутри хуков для отдельных компонентов.
  • Глобальные обработчики ошибок через window.onerror и window.onunhandledrejection.
  • Реактивное состояние ошибок с useState для UI-обратной связи.
  • Интеграция с внешними сервисами для аналитики и логирования.
  • Fallback UI и SafeWrapper-компоненты для предотвращения падения интерфейса.

Такой подход обеспечивает высокую устойчивость приложения и позволяет своевременно выявлять и устранять ошибки.