«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > GlobalErrorHandler: ловите ошибки, которые ускользают из рук ErrorBoundary!

GlobalErrorHandler: ловите ошибки, которые ускользают из рук ErrorBoundary!

Опубликовано 7 ноября 2024 г.
Просматривать:726

GlobalErrorHandler: Catch the errors that falls through ErrorBoundary

ErrorBoundary — великолепный инструмент для отслеживания ошибок, возникающих в компонентах React. Вы можете предоставить собственные сообщения об ошибках в зависимости от характера и места самой ошибки. Но не все возникающие ошибки обрабатываются ErrorBoundary! Что ты с ними делаешь?

При рассмотрении как асинхронных ошибок, так и ошибок, возникающих за пределами React, ErrorBoundary не соответствует действительности. Чтобы смягчить это, я в своих приложениях создал то, что я называю GlobalErrorHandler. Функциональный компонент, который: А) выводит всплывающее диалоговое окно с сообщением пользователю, что что-то пошло не так, Б) регистрирует ошибку на сервере, чтобы мы могли исследовать и найти решения.

Идея проста. Нам нужен один GlobalErrorHandler в корне нашего приложения. Этот обработчик должен обрабатывать только ошибки, не обнаруженные ErrorBoundary. Более того, пользователь должен легко закрыть его, и мы должны предположить, что приложение по-прежнему можно использовать.

Итак, стратегия такова: GlobalErrorHandler вообще ничего не делает, кроме рендеринга своих дочерних элементов по умолчанию. Но он настраивает два прослушивателя событий, которые прослушивают все события ошибок и необработанных отклонений в браузере. Затем он исследует ошибку и проверяет, была ли она уже обработана какими-либо ErrorBoundaries. Наконец, если это не так, появляется диалоговое окно, сообщающее пользователю, что где-то что-то пошло не так, и позволяет пользователю закрыть диалоговое окно и продолжить использование приложения.

Ошибка уже устранена

Прежде чем приставать к конечным пользователям ненужными диалогами ПОВЕРХ обработки, выполняемой ErrorBoundary, мы сначала должны начать с запроса об ошибке: вас уже обработали? Мое решение — добавить новое поле в объект ошибки isHandledByBoundary. Для этого параметра установлено значение true в ErrorBoundary:

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }

При наличии этого во всех компонентах ErrorBoundary (и других механизмах, которые обрабатывают неперехваченные ошибки), мы готовы приступить к определению нашего GlobalErrorHandler.

Голый скелет

Затем мы можем построить скелет нашего GlobalErrorHandler. Он напрямую отображает свои дочерние элементы, а также отображает «ErrorDialog», определенный в другом месте. (Если вы хотите использовать этот компонент совместно с приложениями, вместо него можно использовать ErrorDialog.)

import { useState, useEffect, ReactNode } from 'react';
import { ErrorDialog } from '../Components/ErrorDialog';

type Props = {
  children: ReactNode;
};

export function GlobalErrorHandler({ children }: Props) {
  const [error, setError] = useState(null);
  const [isDialogOpen, setDialogOpen] = useState(false);

  useEffect(() => {
    ....
  }, []);

  function handleCloseDialog() {
    setDialogOpen(false);
    setError(null);
  }

  return (
    
      {children}

      {isDialogOpen && error && (
        
      )}
    >
  );
}

Единственное, чего нам сейчас не хватает, — это самой обработки ошибок, определенной в useEffect.

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

Весь код в этом разделе должен находиться внутри функции useEffect!

Сначала мы определяем handleWindowError. Это сообщение должно быть доставлено обработчику событий ошибок в объекте окна. Здесь нет ничего загадочного, но обратите внимание, что событие ошибки также содержит информацию об источнике, номере строки и номере столбца. Которые могут быть ценными для коллекционирования.

Обычно эта информация также находится в объекте ошибки, но мне нужно провести дополнительные эмпирические исследования. Возможно, нам всегда следует сохранять номера строк и столбцов такими, как сообщает событие ошибки? В этом случае мы также могли бы иметь состояние для этого в GlobalErrorHandler (и убедиться, что оно отправляется при регистрации ошибки).

   function handleWindowError(
      message: string | Event,
      source?: string,
      lineno?: number,
      colno?: number,
      error?: Error
    ) {
      if (error && (error as any).isHandledByBoundary) {
        return true;
      }

      const errorMessage = error
        ? error
        : `Error: ${message} at ${source}:${lineno}:${colno}`;
      setError(errorMessage);
      setDialogOpen(true);
      return true;
    }

Мы также определим обработчик handleUnhandledRejection. Это для ошибок, возникающих в промисах, но мы забыли написать предложение .catch().

    function handleUnhandledRejection(event: PromiseRejectionEvent) {
      setError(`Unhandled promise rejection: ${event.reason}`);
      setDialogOpen(true);
    }

Тогда все, что нам нужно сделать, это настроить прослушиватели и удалять их всякий раз, когда GlobalErrorHandler больше не отображается:

    window.addEventListener('error', handleWindowError);
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('error', handleWindowError);
      window.removeEventListener(
        'unhandledrejection',
        handleUnhandledRejection
      );
    };

Конечно, операторы return — это то место, где мы возвращаемся из функции, которую передаем useEffect. Это гарантирует, что мы начинаем прослушивать события и обрабатывать их, когда компонент визуализируется, и останавливаемся, когда компонент больше не отображается.

Таким образом, у нас есть GlobalEventHandler для обработки тех неприятных ошибок в нашем React-приложении, которые либо выдаются из асинхронных источников, либо выдаются за пределами компонентов React!

Заявление о выпуске Эта статья воспроизводится по адресу: https://dev.to/lebbe/globalerrorhandler-catch-the-errors-taT-falls-trough-errorboundary-fingers-3m5d?
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3