Error tracking

Ember.js — это мощный JavaScript-фреймворк, который позволяет создавать сложные веб-приложения с минимальными усилиями. Однако при разработке с использованием такого фреймворка, как и при разработке с любым другим инструментом, не обойтись без ошибок. Одной из важнейших задач для разработчика становится правильная обработка ошибок, чтобы приложение оставалось стабильным, а пользователи не сталкивались с непредсказуемым поведением. В Ember.js существует несколько способов для отслеживания и обработки ошибок, от встроенных механизмов до возможности интеграции с внешними сервисами.

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

Каждый маршрут в Ember.js может столкнуться с ошибкой во время выполнения. Это может быть связано с проблемами при загрузке данных, ошибками на сервере или с ошибками в бизнес-логике. Чтобы обработать ошибки, связанные с маршрутом, Ember предоставляет специальные хуки, такие как error и handleError.

error-хук

Маршруты в Ember могут реализовать хук error, который срабатывает, когда происходит ошибка во время обработки маршрута. Хук принимает два параметра: ошибку и информацию о переходе.

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

import Route from '@ember/routing/route';

export default class ApplicationRoute extends Route {
  async model() {
    try {
      let data = await fetchDataFromAPI();
      return data;
    } catch (error) {
      this.transitionTo('error', { error });
    }
  }

  error(error, transition) {
    console.error('Ошибка маршрута:', error);
    return this.store.createRecord('error', { message: error.message });
  }
}

В данном примере при возникновении ошибки в методе model, маршрут переключается на страницу с ошибкой, передавая ошибку в контексте перехода. Хук error обрабатывает ошибку, позволяя зарегистрировать ее или показать пользователю страницу с информацией.

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

Если ошибка возникает в процессе загрузки модели на любом маршруте, можно использовать хук в корневом маршруте или настроить глобальную обработку ошибок в файле app/router.js. Это позволяет перехватывать ошибки, произошедшие на более высоком уровне, и выполнять дополнительные действия, такие как логирование.

import EmberRouter from '@ember/routing/router';
import config from './config/environment';

const Router = EmberRouter.extend({
  location: config.locationType,
  rootURL: config.rootURL
});

Router.map(function() {
  this.route('index', { path: '/' });
  this.route('error');
});

Router.on('routeDidChange', (transition) => {
  if (transition.error) {
    console.log('Произошла ошибка в маршруте:', transition.error);
  }
});

export default Router;

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

Компоненты в Ember.js также могут столкнуться с ошибками, особенно если они взаимодействуют с внешними сервисами или пытаются отобразить данные, которые еще не загружены. Для этого в Ember можно использовать блоки {{#if}} или {{#unless}} для обработки ошибок непосредственно в шаблонах.

Включение обработки ошибок в шаблон компонента

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

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class UserProfileComponent extends Component {
  @tracked user = null;
  @tracked error = null;

  constructor() {
    super(...arguments);
    this.loadUserData();
  }

  async loadUserData() {
    try {
      this.user = await fetchUserData();
    } catch (e) {
      this.error = e;
    }
  }
}

Шаблон компонента:

{{#if this.error}}
  <p>Ошибка загрузки данных: {{this.error.message}}</p>
{{else if this.user}}
  <p>Имя пользователя: {{this.user.name}}</p>
{{/if}}

Этот пример показывает, как можно отобразить ошибку в случае её возникновения при загрузке данных для компонента. Блок {{#if}} проверяет, если есть ошибка, и отображает соответствующее сообщение.

Логирование ошибок

Одной из важнейших частей отслеживания ошибок является их логирование. Ember.js предоставляет механизм для интеграции с внешними сервисами для отправки данных об ошибках. Одним из самых популярных инструментов для этого является Sentry.

Интеграция с Sentry

Для интеграции с Sentry, необходимо установить соответствующий пакет:

ember install @sentry/ember

После установки необходимо настроить Sentry в файле app.js:

import { setupSentry } from '@sentry/ember';

export default class App extends Application {
  constructor() {
    super(...arguments);
    setupSentry();
  }
}

После этого все ошибки, произошедшие в приложении, будут автоматически отправляться в Sentry, что позволяет отслеживать их в реальном времени, получать подробные отчеты и быстрее реагировать на проблемы.

Ошибки в асинхронных операциях

В процессе работы с асинхронными операциями часто возникают ошибки, связанные с задержками в сети или неверным состоянием данных. Ember.js предоставляет механизмы, такие как промисы и async/await, которые позволяют удобно обрабатывать асинхронные ошибки.

Пример асинхронного запроса с обработкой ошибок:

import Route from '@ember/routing/route';

export default class PostRoute extends Route {
  async model(params) {
    try {
      let post = await this.store.findRecord('post', params.post_id);
      return post;
    } catch (e) {
      console.error('Ошибка при загрузке поста:', e);
      return { error: true, message: 'Не удалось загрузить пост.' };
    }
  }
}

В этом примере используется асинхронная операция для получения данных о посте. Если происходит ошибка при запросе, она перехватывается и логируется.

Использование Error Boundaries

С Ember 3.28 был добавлен механизм для работы с ошибками на уровне компонентов — Error Boundaries. Это позволяет компоненты, которые могут столкнуться с ошибками, автоматически “поймать” их и отображать резервный интерфейс, не нарушая работу всего приложения.

Пример использования Error Boundary:

import Component from '@glimmer/component';

export default class ErrorBoundaryComponent extends Component {
  errorOccurred = false;

  handleError(error) {
    console.error('Произошла ошибка в компоненте:', error);
    this.errorOccurred = true;
  }
}

Шаблон:

{{#if this.errorOccurred}}
  <p>Произошла ошибка при загрузке компонента.</p>
{{else}}
  {{yield}}
{{/if}}

Error Boundaries в Ember позволяют лучше организовать обработку ошибок в UI, особенно в случае сложных компонентов, где нужно избежать поломки всей страницы при возникновении локальной ошибки.

Заключение

Обработка ошибок в Ember.js — это важная составляющая устойчивости и стабильности приложения. Возможности для перехвата и обработки ошибок в маршрутах, компонентах и асинхронных операциях позволяют легко управлять ситуациями, когда что-то идет не так. Дополнительная интеграция с внешними сервисами для логирования, такими как Sentry, помогает следить за ошибками в реальном времени, что значительно ускоряет процесс их устранения.