← Назад к вопросам
Что делать если при запросе приходит 500?
1.7 Middle🔥 172 комментариев
#JavaScript Core
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что делать при HTTP 500 ошибке
HTTP 500 Internal Server Error — это ошибка на стороне сервера, указывающая что-то пошло не так при обработке запроса. Как фронтенд-разработчик, нужно понимать как правильно обработать эту ошибку и помочь пользователю.
1. Что означает 500 ошибка
HTTP 500 указывает на проблему на сервере, а не на клиенте:
// 500 ошибка означает:
// - Необработанное исключение на сервере
// - Ошибка в коде бэкенда
// - Проблема с базой данных
// - Переполнение памяти на сервере
// - Проблема с внешним API
// - Конфигурация сервера
// Это НЕ ошибка со стороны клиента (как 400, 404)
2. Базовая обработка в fetch
// ❌ Неправильно: не проверяем статус
fetch("/api/data")
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error("Network error:", err));
// ✅ Правильно: проверяем статус ответа
fetch("/api/data")
.then(res => {
if (!res.ok) {
// res.ok = false при статусах 4xx и 5xx
throw new Error(`HTTP Error: ${res.status} ${res.statusText}`);
}
return res.json();
})
.then(data => console.log(data))
.catch(err => console.error("Error:", err));
3. Обработка с axios
// axios автоматически выбросит ошибку при 4xx и 5xx
import axios from "axios";
// ✅ Обработка 500 ошибки
axios
.get("/api/data")
.then(res => console.log(res.data))
.catch(err => {
if (err.response?.status === 500) {
console.error("Server error: 500");
// Обработка 500 ошибки
} else if (err.response?.status >= 500) {
console.error("Server error:", err.response.status);
} else if (err.request) {
console.error("No response:", err.request);
} else {
console.error("Error:", err.message);
}
});
4. Обработка с async/await
// ✅ Современный подход с async/await
async function fetchData() {
try {
const response = await fetch("/api/data");
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Fetch error:", error);
// Обработать ошибку
throw error;
}
}
// Использование
try {
const data = await fetchData();
console.log(data);
} catch (err) {
if (err.message.includes("500")) {
console.error("Server error, please try again later");
}
}
5. Отобразить сообщение об ошибке пользователю
// ✅ Показать пользователю понятное сообщение
async function loadUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
if (response.status === 500) {
showErrorMessage(
"Sorry, our servers are having issues. Please try again later."
);
} else if (response.status === 404) {
showErrorMessage("User not found.");
} else {
showErrorMessage(
`Server error: ${response.status}. Please try again."
);
}
return null;
}
return await response.json();
} catch (error) {
showErrorMessage("Network error. Please check your connection.");
return null;
}
}
function showErrorMessage(message) {
const errorDiv = document.getElementById("error-message");
errorDiv.textContent = message;
errorDiv.style.display = "block";
}
6. Retry механизм (повторные попытки)
// ✅ Повторить запрос при 500 ошибке
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.ok) {
return await response.json();
}
// 500 ошибка — можно повторить
if (response.status >= 500 && i < maxRetries - 1) {
// Экспоненциальная задержка
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) {
throw error;
}
}
}
}
// Использование
try {
const data = await fetchWithRetry("/api/data");
console.log(data);
} catch (error) {
console.error("Failed after retries:", error);
}
7. React компонент с обработкой 500
import { useState, useEffect } from "react";
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const loadUser = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
if (response.status === 500) {
setError(
"Server error. Please try again later."
);
} else if (response.status === 404) {
setError("User not found.");
} else {
setError(`Error: ${response.status}`);
}
return;
}
const data = await response.json();
setUser(data);
} catch (err) {
setError("Network error. Please check your connection.");
} finally {
setLoading(false);
}
};
loadUser();
}, [userId]);
if (loading) return <div>Loading...</div>;
if (error) return <div className="error">{error}</div>;
if (!user) return <div>No user data</div>;
return <div className="user-profile">...</div>;
}
8. Логирование ошибок для отладки
// ✅ Логировать 500 ошибки для отладки
async function apiCall(endpoint, options = {}) {
try {
const response = await fetch(endpoint, options);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
// Логировать ошибку
console.error("API Error:", {
status: response.status,
endpoint,
message: errorData.message,
timestamp: new Date().toISOString()
});
// Отправить в сервис мониторинга (Sentry, Rollbar и т.д.)
if (response.status === 500) {
reportErrorToService({
type: "server_error",
endpoint,
status: response.status,
message: errorData.message
});
}
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error("Request failed:", error);
throw error;
}
}
function reportErrorToService(errorInfo) {
// Отправить в Sentry, Rollbar, или собственный сервис
navigator.sendBeacon("/api/errors", JSON.stringify(errorInfo));
}
9. Circuit Breaker паттерн
// ✅ Временно отключить функционал при частых 500 ошибках
class CircuitBreaker {
constructor(apiCall, threshold = 5, timeout = 60000) {
this.apiCall = apiCall;
this.threshold = threshold;
this.timeout = timeout;
this.failures = 0;
this.isOpen = false;
this.lastFailureTime = null;
}
async call(url) {
// Если circuit открыт, ждём timeout
if (this.isOpen) {
const timeSinceLastFailure = Date.now() - this.lastFailureTime;
if (timeSinceLastFailure < this.timeout) {
throw new Error("Circuit breaker is OPEN");
}
// Попробовать восстановиться
this.isOpen = false;
this.failures = 0;
}
try {
const data = await this.apiCall(url);
this.failures = 0;
return data;
} catch (error) {
this.failures++;
this.lastFailureTime = Date.now();
if (this.failures >= this.threshold) {
this.isOpen = true;
console.error("Circuit breaker OPENED after", this.failures, "failures");
}
throw error;
}
}
}
// Использование
const breaker = new CircuitBreaker(
(url) => fetch(url).then(r => r.json()),
5, // Открыть circuit после 5 ошибок
30000 // На 30 секунд
);
try {
const data = await breaker.call("/api/data");
} catch (error) {
if (error.message === "Circuit breaker is OPEN") {
console.log("Too many errors, using cached data");
}
}
10. Offline режим с caching
// ✅ Использовать кешированные данные при 500 ошибке
async function fetchWithCache(url) {
try {
const response = await fetch(url);
if (!response.ok) {
// При ошибке, попробовать из кеша
const cached = localStorage.getItem(`cache:${url}`);
if (cached) {
console.warn("Using cached data due to error");
return JSON.parse(cached);
}
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// Сохранить в кеш
localStorage.setItem(`cache:${url}`, JSON.stringify(data));
return data;
} catch (error) {
// Попытаться использовать кеш
const cached = localStorage.getItem(`cache:${url}`);
if (cached) {
console.warn("Network error, using cached data");
return JSON.parse(cached);
}
throw error;
}
}
11. Различие ошибок на сервере
// ✅ Правильно различать разные ошибки
async function handleResponse(response) {
if (!response.ok) {
const status = response.status;
// 4xx — ошибка клиента
if (status >= 400 && status < 500) {
if (status === 400) return "Bad request: check your input";
if (status === 401) return "Unauthorized: please login";
if (status === 403) return "Forbidden: no access";
if (status === 404) return "Not found";
if (status === 429) return "Too many requests: please wait";
}
// 5xx — ошибка сервера
if (status >= 500) {
if (status === 500) return "Server error: please try again later";
if (status === 502) return "Bad gateway: service unavailable";
if (status === 503) return "Service unavailable: maintenance mode";
if (status === 504) return "Gateway timeout: request took too long";
}
return `Unknown error: ${status}`;
}
}
12. Monitoring и alerting
// ✅ Отслеживать 500 ошибки для мониторинга
const errorMetrics = {
count: 0,
lastError: null,
endpoints: {}
};
async function monitoredFetch(url, options = {}) {
try {
const response = await fetch(url, options);
if (!response.ok && response.status >= 500) {
errorMetrics.count++;
errorMetrics.lastError = new Date();
errorMetrics.endpoints[url] = (errorMetrics.endpoints[url] || 0) + 1;
// Alert if too many errors
if (errorMetrics.count > 10) {
console.error("Too many server errors!");
sendAlert("High error rate detected");
}
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
throw error;
}
}
function sendAlert(message) {
// Отправить алерт в Slack, email или другой канал
console.error("ALERT:", message);
}
13. Чеклист обработки 500 ошибки
Для пользователя:
- Показать понятное сообщение об ошибке
- Не показывать технические детали
- Предложить действие (повторить, переключиться на другую страницу)
- Показать примерное время восстановления (если известно)
Для разработчика:
- Логировать ошибку с контекстом
- Отправлять в сервис мониторинга
- Реализовать retry механизм
- Добавить обработку с кешированием
- Проверить логи сервера
14. Практический пример целиком
class APIClient {
constructor() {
this.retryCount = 3;
this.retryDelay = 1000;
}
async fetch(url, options = {}) {
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
if (response.status >= 500 && attempt < this.retryCount) {
// Повторить при 5xx
const delay = this.retryDelay * Math.pow(2, attempt - 1);
console.log(`Retry attempt ${attempt} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw new APIError(response.status, await response.text());
}
return await response.json();
} catch (error) {
if (attempt === this.retryCount) {
console.error("API call failed after retries:", error);
throw error;
}
}
}
}
}
class APIError extends Error {
constructor(status, message) {
super(`API Error ${status}: ${message}`);
this.status = status;
}
}
Заключение
При получении 500 ошибки нужно:
- Обработать — проверить статус ответа
- Сообщить — показать пользователю понятное сообщение
- Повторить — реализовать retry механизм
- Логировать — записать ошибку для отладки
- Мониторить — отслеживать частоту ошибок
500 ошибка — это проблема сервера, но как фронтенд-разработчик ты можешь сделать пользовательский опыт лучше, правильно обработав такие ошибки.