← Назад к вопросам

Как писал запросы к API?

2.2 Middle🔥 132 комментариев
#Браузер и сетевые технологии

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как писать запросы к API в Frontend

Основные подходы в современной разработке

Для запросов к API я использую несколько проверенных методов, в зависимости от контекста проекта. Наиболее распространённый вариант — это использование встроенного Fetch API с дополнительными утилитами для обработки ошибок и типизации.

Fetch API с типизацией (TypeScript)

// lib/api.ts
interface ApiResponse<T> {
  data: T;
  status: number;
  success: boolean;
}

async function fetchApi<T>(
  url: string,
  options?: RequestInit
): Promise<ApiResponse<T>> {
  try {
    const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}${url}`, {
      headers: {
        'Content-Type': 'application/json',
        ...options?.headers,
      },
      ...options,
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }

    const data = await response.json();
    return {
      data,
      status: response.status,
      success: true,
    };
  } catch (error) {
    console.error('API request failed:', error);
    return {
      data: null as unknown as T,
      status: 0,
      success: false,
    };
  }
}

export const api = {
  get: <T,>(url: string) => fetchApi<T>(url, { method: 'GET' }),
  post: <T,>(url: string, body: unknown) =>
    fetchApi<T>(url, { method: 'POST', body: JSON.stringify(body) }),
  put: <T,>(url: string, body: unknown) =>
    fetchApi<T>(url, { method: 'PUT', body: JSON.stringify(body) }),
};

Использование в компонентах (React)

// components/UserProfile.tsx
import { useEffect, useState } from 'react';
import { api } from '@/lib/api';

interface User {
  id: string;
  name: string;
  email: string;
}

export function UserProfile() {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const response = await api.get<User>('/users/me');
        if (response.success) {
          setUser(response.data);
        } else {
          setError('Failed to load user');
        }
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Unknown error');
      } finally {
        setLoading(false);
      }
    };

    fetchUser();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div className="text-red-600">{error}</div>;
  if (!user) return <div>No user data</div>;

  return (
    <div className="p-4">
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

Работа с заголовками и аутентификацией

Для безопасной работы с токенами аутентификации нужно правильно управлять заголовками запроса:

// lib/api.ts
const getAuthToken = () => localStorage.getItem('authToken');

async function fetchApi<T>(
  url: string,
  options?: RequestInit
): Promise<ApiResponse<T>> {
  const token = getAuthToken();
  const headers: HeadersInit = {
    'Content-Type': 'application/json',
    ...options?.headers,
  };

  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  // rest of implementation
}

Обработка разных типов ответов

Для работы с различными типами данных — изображениями, файлами, бинарными данными:

// Для работы с изображениями и файлами
async function fetchFile(url: string): Promise<Blob> {
  const response = await fetch(url);
  return response.blob();
}

// Для загрузки файлов
async function uploadFile(url: string, file: File): Promise<void> {
  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch(url, {
    method: 'POST',
    body: formData,
  });

  if (!response.ok) throw new Error('Upload failed');
}

Ключевые принципы: обработка ошибок на уровне приложения, использование типизации для безопасности, никогда не храним чувствительные данные в localStorage без защиты.