Базовый пример с обработкой всех типов ошибок:
async function fetchWithErrorHandling(url) {
try {
const response = await fetch(url);
if (!response.ok) {
// Обработка HTTP-ошибок (4xx, 5xx)
const errorData = await response.json().catch(() => null);
throw {
status: response.status,
message: errorData?.message || 'HTTP request failed',
data: errorData
};
}
return await response.json();
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request was aborted');
} else if (error instanceof TypeError) {
console.error('Network error:', error.message);
} else {
console.error('Request failed:', error);
}
throw error; // Пробрасываем ошибку дальше
}
}
Axios предоставляет более структурированную обработку ошибок:
try {
const response = await axios.get('/api/data');
// Обработка успешного ответа
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled:', error.message);
} else if (error.response) {
// Сервер ответил с кодом ошибки (4xx, 5xx)
console.error('Server error:', error.response.status);
console.error('Error data:', error.response.data);
} else if (error.request) {
// Запрос был сделан, но ответ не получен
console.error('No response received:', error.request);
} else {
// Ошибка при настройке запроса
console.error('Request setup error:', error.message);
}
}
// Добавляем интерсептор для обработки ошибок
axios.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
// Перенаправляем на страницу входа
window.location = '/login';
} else if (error.response?.status === 403) {
// Показываем уведомление о недостатке прав
showNotification('У вас нет доступа к этому ресурсу');
}
return Promise.reject(error);
}
);
async function safeFetch(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) throw response;
return await response.json();
} catch (error) {
if (error.status === 401) handleUnauthorized();
if (error.status === 404) handleNotFound();
throw error;
}
}
function useApi(endpoint) {
const [state, setState] = useState({
data: null,
loading: true,
error: null
});
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await fetch(endpoint, {
signal: controller.signal
});
if (!response.ok) throw await response.json();
setState({
data: await response.json(),
loading: false,
error: null
});
} catch (error) {
if (error.name !== 'AbortError') {
setState({
data: null,
loading: false,
error: error.message || 'Request failed'
});
}
}
};
fetchData();
return () => controller.abort();
}, [endpoint]);
return state;
}
function UserProfile() {
const { data, loading, error } = useApi('/api/user');
if (loading) return <Spinner />;
if (error) return <ErrorDisplay message={error} />;
return (
<div>
<h1>{data.name}</h1>
{/* ... */}
</div>
);
}
function logError(error) {
fetch('/api/error-log', {
method: 'POST',
body: JSON.stringify({
error: error.toString(),
stack: error.stack,
timestamp: new Date().toISOString()
})
});
}
import * as Sentry from '@sentry/react';
try {
// API запрос
} catch (error) {
Sentry.captureException(error);
throw error;
}
async function fetchWithRetry(url, retries = 3) {
try {
return await fetch(url);
} catch (error) {
if (retries <= 0) throw error;
await new Promise(res => setTimeout(res, 1000));
return fetchWithRetry(url, retries - 1);
}
}
class ApiCircuitBreaker {
constructor(maxFailures = 3, cooldown = 30000) {
this.failures = 0;
this.lastFailure = 0;
this.maxFailures = maxFailures;
this.cooldown = cooldown;
}
async call(fn) {
if (this.failures >= this.maxFailures) {
if (Date.now() - this.lastFailure < this.cooldown) {
throw new Error('Service unavailable (circuit breaker)');
}
this.failures = 0;
}
try {
const result = await fn();
this.failures = 0;
return result;
} catch (error) {
this.failures++;
this.lastFailure = Date.now();
throw error;
}
}
}
эффективная обработка ошибок в HTTP-запросах требует: