Обработка ошибок
Kodzero SDK предоставляет специальные классы ошибок для удобной обработки различных исключительных ситуаций.
Типы ошибок
KodzeroApiError
Возникает при ошибках API-запросов (4xx, 5xx ответы от сервера):
typescript
class KodzeroApiError extends Error {
name: 'KodzeroApiError'
url: string // URL запроса
statusCode: number // HTTP код ответа
message: string // Сообщение об ошибке
details: string // Дополнительные детали
}KodzeroValidationError
Возникает при ошибках валидации данных:
typescript
class KodzeroValidationError extends Error {
name: 'KodzeroValidationError'
message: string // Сообщение об ошибке
errors: string[] // Массив ошибок валидации
}Обработка ошибок API
Базовый пример
typescript
try {
const user = await User.get('non_existent_id')
} catch (error) {
if (error.name === 'KodzeroApiError') {
console.error('API ошибка:', error.message)
console.error('HTTP код:', error.statusCode)
console.error('URL:', error.url)
} else {
console.error('Неизвестная ошибка:', error)
}
}Обработка по HTTP-кодам
typescript
try {
await kodzero.auth.login({ email, password })
} catch (error) {
if (error.name === 'KodzeroApiError') {
switch (error.statusCode) {
case 400:
// Неверный запрос
alert('Проверьте введённые данные')
break
case 401:
// Не авторизован
alert('Неверный email или пароль')
break
case 403:
// Доступ запрещён
alert('Доступ запрещён')
break
case 404:
// Не найдено
alert('Пользователь не найден')
break
case 429:
// Слишком много запросов
alert('Слишком много попыток. Подождите.')
break
case 500:
// Ошибка сервера
alert('Ошибка сервера. Попробуйте позже.')
break
default:
alert(`Ошибка: ${error.message}`)
}
}
}Обработка ошибок валидации
typescript
try {
const validation = user.validate()
if (!validation.ok) {
throw new KodzeroValidationError(
'Ошибка валидации',
validation.errors
)
}
await user.save()
} catch (error) {
if (error.name === 'KodzeroValidationError') {
console.error('Ошибки валидации:', error.errors)
// ['name is required', 'email is required']
}
}Глобальная обработка ошибок
React Error Boundary
tsx
import { Component, ErrorInfo, ReactNode } from 'react'
interface Props {
children: ReactNode
}
interface State {
hasError: boolean
error: Error | null
}
class KodzeroErrorBoundary extends Component<Props, State> {
state: State = {
hasError: false,
error: null
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
if (error.name === 'KodzeroApiError') {
console.error('Kodzero API Error:', error)
// Отправить в систему мониторинга
}
}
render() {
if (this.state.hasError) {
const error = this.state.error
if (error?.name === 'KodzeroApiError') {
return (
<div className="error-page">
<h1>Ошибка загрузки данных</h1>
<p>{error.message}</p>
<button onClick={() => window.location.reload()}>
Обновить страницу
</button>
</div>
)
}
return <div>Что-то пошло не так</div>
}
return this.props.children
}
}Vue глобальный обработчик
typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.errorHandler = (error, instance, info) => {
if (error.name === 'KodzeroApiError') {
console.error('Kodzero API Error:', error)
// Показать уведомление
if (error.statusCode === 401) {
// Перенаправить на страницу входа
router.push('/login')
}
}
}
app.mount('#app')Утилита для обработки ошибок
Создайте универсальную функцию для обработки ошибок:
typescript
interface ErrorHandlerResult {
message: string
code?: number
isApiError: boolean
isValidationError: boolean
errors?: string[]
}
function handleKodzeroError(error: unknown): ErrorHandlerResult {
// API ошибка
if (error instanceof Error && error.name === 'KodzeroApiError') {
const apiError = error as any
return {
message: apiError.message,
code: apiError.statusCode,
isApiError: true,
isValidationError: false
}
}
// Ошибка валидации
if (error instanceof Error && error.name === 'KodzeroValidationError') {
const validationError = error as any
return {
message: validationError.message,
isApiError: false,
isValidationError: true,
errors: validationError.errors
}
}
// Другие ошибки
return {
message: error instanceof Error ? error.message : 'Неизвестная ошибка',
isApiError: false,
isValidationError: false
}
}
// Использование
try {
await User.create(data)
} catch (error) {
const result = handleKodzeroError(error)
if (result.isApiError) {
if (result.code === 401) {
// Обработка 401
}
} else if (result.isValidationError) {
// Показать ошибки валидации
showErrors(result.errors)
}
}React Hook для обработки ошибок
typescript
import { useState, useCallback } from 'react'
interface UseApiErrorResult<T> {
execute: (fn: () => Promise<T>) => Promise<T | null>
error: Error | null
isApiError: boolean
statusCode: number | null
clearError: () => void
}
function useApiError<T = any>(): UseApiErrorResult<T> {
const [error, setError] = useState<Error | null>(null)
const execute = useCallback(async (fn: () => Promise<T>) => {
setError(null)
try {
return await fn()
} catch (e) {
setError(e as Error)
return null
}
}, [])
const clearError = useCallback(() => {
setError(null)
}, [])
return {
execute,
error,
isApiError: error?.name === 'KodzeroApiError',
statusCode: (error as any)?.statusCode || null,
clearError
}
}
// Использование
function UserProfile() {
const { execute, error, isApiError, statusCode, clearError } = useApiError()
const loadUser = async () => {
const user = await execute(() => User.get('user_id'))
if (user) {
// Успех
}
}
return (
<div>
{error && (
<div className="error">
{isApiError
? `Ошибка API (${statusCode}): ${error.message}`
: error.message}
<button onClick={clearError}>Закрыть</button>
</div>
)}
{/* ... */}
</div>
)
}Retry логика
typescript
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
let lastError: Error | null = null
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn()
} catch (error) {
lastError = error as Error
// Не повторять для некоторых ошибок
if (error.name === 'KodzeroApiError') {
const statusCode = (error as any).statusCode
// Не повторять для клиентских ошибок
if (statusCode >= 400 && statusCode < 500) {
throw error
}
}
// Ждём перед повторной попыткой
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, delay * attempt))
}
}
}
throw lastError
}
// Использование
const users = await withRetry(
() => User.findMany({ page: 1, perPage: 10 }),
3,
1000
)