Сетевые запросы в JS - эффективные методы и инструменты

Раздел: JavaScript -> Сетевое взаимодействие

HTTP запросы в JavaScript: обзор и эффективные решения

Как выполнить HTTP запросы в JavaScript с помощью fetch?

fetch - это встроенный API для выполнения сетевых запросов. Он возвращает Promise, что упрощает асинхронную обработку.

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) throw new Error('Ошибка ' + response.status);
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error('Ошибка:', error));

Js запросы (http запросы в javascript)

После fetch нужно преобразовать ответ в нужный формат (json, text, blob). Важно проверять response.ok, так как fetch не отклоняет Promise при HTTP ошибках (4xx, 5xx).

Типичные ошибки: пропущена проверка статуса, не вызван метод .json(), CORS политика, неверный URL.

Как выполнить HTTP запросы с помощью XMLHttpRequest?

XMLHttpRequest - классический способ, поддерживает события и прогресс загрузки.

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data');
xhr.onload = function() {
  if (xhr.status >= 200 && xhr.status < 300) {
    console.log(JSON.parse(xhr.responseText));
  } else {
    console.error('Ошибка ' + xhr.status);
  }
};
xhr.onerror = function() {
  console.error('Сетевая ошибка');
};
xhr.send();

Методы open, onload, send. Можно слушать onprogress для отслеживания загрузки.

Проблемы: больше кода, сложность с синхронными запросами (устарело), необходимость вручную обрабатывать разные типы данных.

Как упростить асинхронные запросы с async/await?

Синтаксис async/await делает код более читаемым, похожим на синхронный.

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) throw new Error('Ошибка ' + response.status);
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Ошибка:', error);
  }
}
fetchData();

Функция объявляется с ключевым словом async, перед промисами ставится await, ошибки обрабатываются через try/catch.

Ошибки: await вне функции async, забыли обернуть вызов в try/catch.

Как отправить данные на сервер в формате JSON?

Для POST запроса с JSON нужно указать method, заголовки и тело.

fetch('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Иван', age: 30 })
})
.then(response => response.json())
.then(data => console.log(data));

Тело запроса преобразуется в строку через JSON.stringify, заголовок Content-Type обязателен.

Ошибки: неверный Content-Type, некорректный JSON в теле, отсутствие метода.

Как передать файлы и данные формы через HTTP?

Для отправки форм с файлами используется FormData.

const form = new FormData();
form.append('username', 'user1');
form.append('avatar', fileInput.files[0]);

fetch('/upload', {
  method: 'POST',
  body: form
})
.then(response => response.json())
.then(data => console.log(data));

FormData автоматически устанавливает multipart/form-data, заголовок Content-Type указывать не нужно.

Проблемы: сервер должен поддерживать multipart, размер файла может быть ограничен, не забыть проверить fileInput.

Как добавить пользовательские заголовки к запросу?

Заголовки передаются в объекте headers.

fetch('https://api.example.com/data', {
  headers: {
    'Authorization': 'Bearer token123',
    'X-Custom-Header': 'customValue'
  }
})
.then(response => response.json())
.then(data => console.log(data));

Можно добавить несколько заголовков, включая авторизацию.

Ошибки: CORS может запретить некоторые заголовки, неверное имя заголовка.

Как корректно обрабатывать ошибки при HTTP запросах?

Необходимо проверять статус ответа и обрабатывать как сетевые, так и HTTP ошибки.

fetch('/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('HTTP ошибка ' + response.status);
    }
    return response.json();
  })
  .catch(error => {
    if (error.name === 'TypeError') {
      console.error('Сетевая ошибка');
    } else {
      console.error('Ошибка ответа:', error.message);
    }
  });

Сетевые ошибки (например, отсутствие интернета) вызывают TypeError, HTTP ошибки обрабатываются через свой статус.

Распространённые ошибки: отсутствие catch, игнорирование response.ok, путаница между типами ошибок.

Какие преимущества дает библиотека axios?

axios - популярная библиотека, упрощающая HTTP запросы, автоматически преобразует JSON, поддерживает interceptor'ы, таймауты, отмену запросов.

// Установка: npm install axios
import axios from 'axios';

axios.get('https://api.example.com/data')
  .then(response => console.log(response.data))
  .catch(error => console.error('Ошибка:', error));

В отличие от fetch, axios автоматически парсит JSON, отклоняет Promise при HTTP ошибках (4xx, 5xx), имеет удобный API для заголовков и параметров.

Недостатки: дополнительная зависимость, размер библиотеки, может быть избыточной для простых запросов.

Расширенные примеры HTTP запросов

Пример 1: Параллельные запросы с Promise.all

Пример
const urls = ['https://api.example.com/users', 'https://api.example.com/posts', 'https://api.example.com/comments'];
const fetchAll = async () => {
  try {
    const promises = urls.map(url => fetch(url).then(res => res.json()));
    const results = await Promise.all(promises);
    console.log('Получены данные:', results);
  } catch (error) {
    console.error('Ошибка при загрузке:', error);
  }
};
fetchAll();
// Результат: массив из трёх объектов (users, posts, comments)

Пример 2: Отмена запроса с AbortController

Пример
const controller = new AbortController();
const signal = controller.signal;

setTimeout(() => controller.abort(), 3000); // отмена через 3 секунды

fetch('https://api.example.com/large-data', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Запрос был отменён');
    } else {
      console.error('Ошибка:', error);
    }
  });
// Вывод: 'Запрос был отменён'

Пример 3: Прогресс загрузки через XMLHttpRequest

Пример
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/bigfile');
xhr.onprogress = function(event) {
  if (event.lengthComputable) {
    const percent = (event.loaded / event.total) * 100;
    console.log(`Загружено ${percent.toFixed(1)}%`);
  }
};
xhr.onload = function() {
  console.log('Загрузка завершена');
};
xhr.send();
// Вывод: 'Загружено 23.5%', 'Загружено 57.2%', ..., 'Загрузка завершена'

Пример 4: Интерцепторы в axios

Пример
import axios from 'axios';

axios.interceptors.request.use(config => {
  config.headers['Authorization'] = 'Bearer ' + localStorage.getItem('token');
  console.log('Запрос отправлен', config);
  return config;
}, error => Promise.reject(error));

axios.interceptors.response.use(response => {
  console.log('Ответ получен', response);
  return response;
}, error => {
  if (error.response.status === 401) {
    console.log('Перенаправление на страницу логина');
  }
  return Promise.reject(error);
});

axios.get('/api/profile');
// В консоли: 'Запрос отправлен' затем 'Ответ получен'

Пример 5: Таймаут запроса с axios

Пример
axios.get('https://api.example.com/slow', { timeout: 5000 })
  .then(response => console.log(response.data))
  .catch(error => {
    if (error.code === 'ECONNABORTED') {
      console.log('Таймаут запроса');
    } else {
      console.error('Ошибка:', error);
    }
  });
// Вывод: 'Таймаут запроса'

Пример 6: DELETE запрос с fetch

Пример
fetch('https://api.example.com/users/123', { method: 'DELETE' })
  .then(response => {
    if (response.status === 204) {
      console.log('Ресурс удалён');
    } else {
      return response.json();
    }
  })
  .then(data => console.log(data));
// Вывод: 'Ресурс удалён' или объект с подтверждением

Пример 7: Загрузка изображения как Blob

Пример
fetch('https://example.com/image.png')
  .then(response => response.blob())
  .then(blob => {
    const imgUrl = URL.createObjectURL(blob);
    document.getElementById('myImage').src = imgUrl;
  })
  .catch(error => console.error('Ошибка загрузки изображения:', error));
// Результат: изображение отображается на странице

HTTP запросы в JavaScript - comments

En
Js запросы (javascript)