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

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


Использование блоков try-catch в компонентах

В SvelteKit UI библиотеках компоненты часто получают данные через асинхронные запросы или пропсы. Для безопасной обработки ошибок применяется конструкция try-catch:

<script>
  import { onMount } from 'svelte';
  import { fetchData } from '../api/data.js';
  
  let data;
  let error = null;

  onMount(async () => {
    try {
      data = await fetchData();
    } catch (err) {
      error = err.message;
    }
  });
</script>

{#if error}
  <div class="error">{error}</div>
{:else if data}
  <div class="content">{data}</div>
{/if}

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


Обработка ошибок в load функциях

SvelteKit использует load функции для предварительной загрузки данных на маршрутах. Ошибки, возникающие в этих функциях, можно обрабатывать с помощью встроенных объектов error и redirect.

// src/routes/[id]/+page.js
import { error } from '@sveltejs/kit';

export async function load({ params, fetch }) {
  try {
    const res = await fetch(`/api/items/${params.id}`);
    if (!res.ok) throw new Error('Не удалось загрузить данные');
    const item = await res.json();
    return { item };
  } catch (err) {
    throw error(500, err.message);
  }
}

Особенности:

  • Использование throw error(status, message) позволяет SvelteKit автоматически рендерить страницу ошибки.
  • Ошибки с разными статусами (404, 401, 500) можно маршрутизировать на соответствующие страницы.

Глобальная обработка ошибок через hooks

Для централизованной обработки ошибок на уровне приложения применяется handleError в src/hooks.server.js:

export function handleError({ error, event }) {
  console.error('Произошла ошибка:', error);
  return {
    message: 'Произошла внутренняя ошибка сервера',
    code: error.code ?? 'UNKNOWN'
  };
}

Преимущества:

  • Все необработанные ошибки логируются в одном месте.
  • Можно возвращать единый формат ответа для фронтенд-компонентов.
  • Удобно интегрировать с внешними системами логирования (Sentry, LogRocket).

Интеграция с UI-библиотеками

SvelteKit UI libs, такие как svelte-material-ui, sveltestrap или shadcn-ui, предоставляют компоненты для отображения ошибок:

  • Alert / Toast компоненты для краткого уведомления.
  • Modal окна для подтверждения критических ошибок.
  • Inline ошибки внутри форм и списков.

Пример с использованием Toast уведомления:

<script>
  import { toast } from 'svelte-french-toast';

  async function submitForm(formData) {
    try {
      const res = await fetch('/api/submit', { method: 'POST', body: formData });
      if (!res.ok) throw new Error('Ошибка отправки формы');
      toast.success('Форма успешно отправлена');
    } catch (err) {
      toast.error(err.message);
    }
  }
</script>

Рекомендация: комбинировать реактивное состояние ошибки с визуальными компонентами для улучшения UX.


Обработка ошибок в формах

Формы — частая точка возникновения ошибок. SvelteKit UI библиотеки поддерживают:

  • Валидаторы на уровне компонентов (required, pattern, кастомные функции).
  • Асинхронную проверку на сервере.
  • Вывод сообщений об ошибках прямо под полями ввода.
<script>
  let email = '';
  let emailError = '';

  async function validateEmail() {
    try {
      const res = await fetch(`/api/validate-email?email=${email}`);
      const { valid } = await res.json();
      if (!valid) emailError = 'Email уже занят';
      else emailError = '';
    } catch {
      emailError = 'Ошибка проверки email';
    }
  }
</script>

<input type="email" bind:value={email} on:blur={validateEmail} />
{#if emailError}
  <span class="error">{emailError}</span>
{/if}

Принцип: ошибки должны быть максимально локализованы, чтобы не мешать остальному компоненту.


Стратегии восстановления после ошибок

  • Fallback контент: показывать запасные данные или заглушки.
  • Повторная загрузка: предоставлять кнопку retry при неудачных запросах.
  • Логирование: сохранять ошибки для последующего анализа и исправления.
{#if error}
  <div class="error">
    {error} 
    <button on:click={reload}>Попробовать снова</button>
  </div>
{:else}
  <DataDisplay {data} />
{/if}
  • reload может повторно вызывать асинхронную функцию получения данных.
  • Такой подход улучшает стабильность приложения и повышает доверие пользователей.

Выводы по обработке ошибок

  • Ошибки разделяются на локальные (компонент/форма) и глобальные (маршруты/сервер).
  • Использование try-catch, load, handleError и UI компонентов позволяет контролировать все уровни.
  • В SvelteKit UI libs критично отделять состояние данных от состояния ошибок, обеспечивая реактивное и предсказуемое поведение интерфейса.

Эффективная обработка ошибок в SvelteKit повышает надежность приложений и улучшает пользовательский опыт, особенно при взаимодействии с асинхронными данными и внешними API.