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

Какие использовал способы взаимодействия с Backend?

1.7 Middle🔥 181 комментариев
#JavaScript Core

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

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

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

Способы взаимодействия с Backend

1. Fetch API (современный стандарт)

Fetch API — встроенный в браузер способ делать HTTP запросы. Это переход от старого XMLHttpRequest.

// Простой GET запрос
fetch("/api/v1/users")
  .then((response) => {
    if (!response.ok) throw new Error(`HTTP ${response.status}`);
    return response.json();
  })
  .then((data) => console.log("Users:", data))
  .catch((error) => console.error("Error:", error));

// POST запрос с данными
fetch("/api/v1/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + token,
  },
  body: JSON.stringify({ name: "John", email: "john@example.com" }),
})
  .then((response) => response.json())
  .then((user) => console.log("Created:", user));

// Timeout и abort
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);

fetch("/api/v1/data", { signal: controller.signal })
  .then((response) => response.json())
  .finally(() => clearTimeout(timeoutId));

2. Async/Await (синтаксический сахар над Promises)

// Асинхронная функция с await
async function getUser(userId) {
  try {
    const response = await fetch(`/api/v1/users/${userId}`);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    const user = await response.json();
    return user;
  } catch (error) {
    console.error("Failed to fetch user:", error);
    throw error;
  }
}

// Использование
const user = await getUser(123);
console.log(user);

// Параллельные запросы
const [users, posts] = await Promise.all([
  fetch("/api/v1/users").then((r) => r.json()),
  fetch("/api/v1/posts").then((r) => r.json()),
]);

3. XMLHttpRequest (старый подход, не рекомендуется)

// Старый способ — избегай его
const xhr = new XMLHttpRequest();
xhr.open("GET", "/api/v1/users", true);
xhr.responseType = "json";

xhr.onload = () => {
  if (xhr.status === 200) {
    console.log("Data:", xhr.response);
  }
};

xhr.onerror = () => {
  console.error("Network error");
};

xhr.send();

Problems: verbose, callback hell, сложно обрабатывать ошибки.

4. Библиотеки для HTTP запросов

Axios

import axios from "axios";

// Создание клиента с дефолтными параметрами
const api = axios.create({
  baseURL: "https://api.example.com",
  timeout: 10000,
  headers: { "X-Custom-Header": "value" },
});

// Автоматическое добавление токена ко всем запросам
api.interceptors.request.use((config) => {
  const token = localStorage.getItem("token");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Обработка ошибок глобально
api.interceptors.response.use(
  (response) => response.data,
  (error) => {
    if (error.response?.status === 401) {
      // Перенаправить на логин
    }
    return Promise.reject(error);
  }
);

// Использование
const user = await api.get(`/users/${id}`);
const newUser = await api.post("/users", { name: "John" });

TanStack Query (React Query)

import { useQuery, useMutation } from "@tanstack/react-query";

function UserProfile({ userId }) {
  // Автоматический кеш, рефетч, загрузка ошибок
  const { data: user, isLoading, error } = useQuery({
    queryKey: ["users", userId],
    queryFn: async () => {
      const response = await fetch(`/api/v1/users/${userId}`);
      return response.json();
    },
  });

  // Мутация (POST/PUT/DELETE)
  const updateMutation = useMutation({
    mutationFn: async (updates) =>
      fetch(`/api/v1/users/${userId}`, {
        method: "PUT",
        body: JSON.stringify(updates),
      }).then((r) => r.json()),
    onSuccess: () => {
      // Автоматический рефетч или ручное обновление кеша
      queryClient.invalidateQueries(["users", userId]);
    },
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>{user.name}</h1>
      <button onClick={() => updateMutation.mutate({ name: "Jane" })}>
        Update
      </button>
    </div>
  );
}

SWR (Stale-While-Revalidate)

import useSWR from "swr";

const fetcher = (url) => fetch(url).then((r) => r.json());

function UserList() {
  const { data: users, error } = useSWR("/api/v1/users", fetcher);

  if (error) return <div>Failed to load</div>;
  if (!users) return <div>Loading...</div>;

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

5. GraphQL

import { gql, useQuery } from "@apollo/client";

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
      posts {
        id
        title
      }
    }
  }
`;

function UserProfile({ userId }) {
  const { loading, error, data } = useQuery(GET_USER, {
    variables: { id: userId },
  });

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <div>
      <h1>{data.user.name}</h1>
      <ul>
        {data.user.posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

Преимущества GraphQL:

  • Запрашиваешь только нужные данные (no over-fetching)
  • Одна точка входа (не нужно знать все endpoints)
  • Сильная типизация

6. WebSocket (реал-тайм коммуникация)

// Нативный WebSocket
const socket = new WebSocket("wss://api.example.com/chat");

socket.onopen = () => {
  console.log("Connected");
  socket.send(JSON.stringify({ type: "subscribe", channel: "news" }));
};

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log("Message:", message);
};

socket.onerror = (error) => console.error("Error:", error);
socket.onclose = () => console.log("Disconnected");

// Отправка сообщения
socket.send(JSON.stringify({ type: "message", text: "Hello!" }));

Socket.io (удобнее, с фолбеком на polling)

import io from "socket.io-client";

const socket = io("https://api.example.com", {
  reconnection: true,
  reconnectionDelay: 1000,
  reconnectionDelayMax: 5000,
});

socket.on("connect", () => console.log("Connected"));
socket.on("message", (data) => console.log("Got:", data));
socket.emit("send-message", { text: "Hello" });

7. Server-Sent Events (SSE)

// Одностороннее подключение от сервера к клиенту
const eventSource = new EventSource("/api/v1/stream");

eventSource.addEventListener("update", (event) => {
  const data = JSON.parse(event.data);
  console.log("Update:", data);
});

eventSource.onerror = () => {
  console.error("Connection lost");
  eventSource.close();
};

Этто полезно для пуш-уведомлений и реал-тайм обновлений данных.

8. Обработка ошибок и retry логика

async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  const { retries = maxRetries, ...fetchOptions } = options;

  try {
    const response = await fetch(url, fetchOptions);
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    if (retries > 0 && (error.message.includes("503") || error instanceof TypeError)) {
      // Retry на сервер-ошибки и сетевые проблемы
      await new Promise((resolve) => setTimeout(resolve, 1000));
      return fetchWithRetry(url, { ...options, retries: retries - 1 }, maxRetries);
    }
    throw error;
  }
}

Рекомендации

  • REST API + Fetch — стандартный выбор для большинства проектов
  • Axios — если нужна большая удобство (interceptors, timeout)
  • TanStack Query — если работаешь с кешированием и синхронизацией состояния
  • GraphQL — для сложных данных с множеством связей
  • WebSocket/SSE — для реал-тайма

Выбор способа зависит от типа приложения, требований к реал-тайму и архитектуре бэкенда.

Какие использовал способы взаимодействия с Backend? | PrepBro