feat: Добавление компонентов ErrorBoundary и NetworkErrorHandler для улучшения обработки ошибок в приложении. Увеличение таймаута запросов до 30 секунд и улучшение логики повторных попыток с детализированными уведомлениями об ошибках.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m43s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m43s
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Примеры использования новой системы обработки ошибок
|
||||
* Этот файл демонстрирует различные сценарии использования
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useErrorHandler } from '../hooks/useErrorHandler';
|
||||
import RetryButton from '../components/RetryButton';
|
||||
import api from '../lib/api';
|
||||
|
||||
/**
|
||||
* Пример 1: Простая обработка ошибок в компоненте
|
||||
*/
|
||||
function SimpleErrorHandlingExample() {
|
||||
const [data, setData] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { handleError, handleSuccess, withErrorHandler } = useErrorHandler();
|
||||
|
||||
// Вариант 1: Ручная обработка ошибок
|
||||
const fetchDataManual = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await api.get('/domains-new');
|
||||
setData(response.data);
|
||||
handleSuccess('Данные успешно загружены');
|
||||
} catch (error) {
|
||||
handleError(error, { component: 'SimpleErrorHandlingExample' });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Вариант 2: Автоматическая обработка с withErrorHandler
|
||||
const fetchDataAuto = withErrorHandler(
|
||||
async () => {
|
||||
setLoading(true);
|
||||
const response = await api.get('/domains-new');
|
||||
setData(response.data);
|
||||
setLoading(false);
|
||||
},
|
||||
{
|
||||
successMessage: 'Данные успешно загружены',
|
||||
context: { component: 'SimpleErrorHandlingExample' }
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Пример простой обработки ошибок</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="btn-list">
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={fetchDataManual}
|
||||
disabled={loading}
|
||||
>
|
||||
Загрузить (ручная обработка)
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={fetchDataAuto}
|
||||
disabled={loading}
|
||||
>
|
||||
Загрузить (автоматическая обработка)
|
||||
</button>
|
||||
</div>
|
||||
{data && (
|
||||
<div className="mt-3">
|
||||
<p>Загружено записей: {data.items?.length || 0}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Пример 2: Использование RetryButton
|
||||
*/
|
||||
function RetryButtonExample() {
|
||||
const [attempts, setAttempts] = useState(0);
|
||||
const { handleError, handleSuccess } = useErrorHandler();
|
||||
|
||||
const unreliableOperation = async () => {
|
||||
setAttempts(prev => prev + 1);
|
||||
|
||||
// Симуляция операции которая иногда падает
|
||||
if (Math.random() < 0.5) {
|
||||
throw new Error('Случайная ошибка для демонстрации');
|
||||
}
|
||||
|
||||
handleSuccess('Операция выполнена успешно!');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Пример использования RetryButton</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<p>Попыток: {attempts}</p>
|
||||
<RetryButton
|
||||
onRetry={unreliableOperation}
|
||||
className="btn btn-primary"
|
||||
>
|
||||
Выполнить ненадежную операцию
|
||||
</RetryButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Пример 3: Обработка различных типов ошибок
|
||||
*/
|
||||
function ErrorTypesExample() {
|
||||
const { handleError } = useErrorHandler();
|
||||
|
||||
const triggerNetworkError = () => {
|
||||
api.get('/nonexistent-endpoint')
|
||||
.catch(error => handleError(error));
|
||||
};
|
||||
|
||||
const triggerValidationError = () => {
|
||||
api.post('/domains-new', { invalid: 'data' })
|
||||
.catch(error => handleError(error));
|
||||
};
|
||||
|
||||
const triggerTimeoutError = () => {
|
||||
// Создаем запрос который точно превысит таймаут
|
||||
const slowApi = api.create({ timeout: 100 });
|
||||
slowApi.get('/domains-new')
|
||||
.catch(error => handleError(error));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Типы ошибок</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="btn-list">
|
||||
<button
|
||||
className="btn btn-danger"
|
||||
onClick={triggerNetworkError}
|
||||
>
|
||||
Сетевая ошибка
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-warning"
|
||||
onClick={triggerValidationError}
|
||||
>
|
||||
Ошибка валидации
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-info"
|
||||
onClick={triggerTimeoutError}
|
||||
>
|
||||
Таймаут
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Главный компонент с примерами
|
||||
*/
|
||||
function ErrorHandlingExample() {
|
||||
return (
|
||||
<div className="container-xl">
|
||||
<div className="page-header">
|
||||
<h1 className="page-title">Примеры обработки ошибок</h1>
|
||||
<p className="text-muted">
|
||||
Демонстрация возможностей новой системы обработки ошибок
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="row row-cards">
|
||||
<div className="col-12">
|
||||
<SimpleErrorHandlingExample />
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<RetryButtonExample />
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<ErrorTypesExample />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card mt-3">
|
||||
<div className="card-header">
|
||||
<h3 className="card-title">Особенности новой системы</h3>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<ul>
|
||||
<li>✅ <strong>Автоматический retry</strong> для GET запросов (до 3 попыток)</li>
|
||||
<li>✅ <strong>Умный retry</strong> для POST/PUT/DELETE при сетевых ошибках</li>
|
||||
<li>✅ <strong>Exponential backoff</strong> с jitter для избежания thundering herd</li>
|
||||
<li>✅ <strong>User-friendly сообщения</strong> вместо технических ошибок</li>
|
||||
<li>✅ <strong>Детальная информация</strong> для отладки (requestId, timestamp, детали)</li>
|
||||
<li>✅ <strong>Offline/Online detection</strong> с уведомлениями</li>
|
||||
<li>✅ <strong>Error Boundary</strong> для ловли React ошибок рендеринга</li>
|
||||
<li>✅ <strong>Типизация ошибок</strong> (Network, Timeout, Server, Client, etc.)</li>
|
||||
<li>✅ <strong>Интеграция с системой уведомлений</strong></li>
|
||||
<li>✅ <strong>Логирование критичных ошибок</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ErrorHandlingExample;
|
||||
|
||||
Reference in New Issue
Block a user