fetch()

fetch() — это функция JavaScript, которая используется для отправки сетевых запросов и получения данных с сервера. Она является частью спецификации Fetch API, которая начала поддерживаться в браузерах с 2015 года. fetch() предназначена для выполнения HTTP-запросов и позволяет работать с различными типами данных.


Основное предназначение fetch() — это взаимодействие с внешними API, получение данных с сервера или отправка данных на сервер. fetch() поддерживает различные HTTP-методы, такие как GET, POST, PUT, DELETE, и другие, что делает его универсальным инструментом для работы с различными типами запросов.

Кроме того, fetch() может работать не только с JSON, но и с другими типами данных, такими как Blob, FormData, Text, и даже ArrayBuffer, что позволяет гибко использовать его в самых разных сценариях, например, для загрузки и отправки файлов или бинарных данных. Эта функция возвращает промис, что позволяет легко работать с асинхронными операциями и обрабатывать результаты запроса.

Примеры использования fetch()

fetch() может быть использован в различных сценариях, таких как:

Замена устаревшего XMLHttpRequest

Ранее для выполнения HTTP-запросов в JavaScript использовался объект XMLHttpRequest. Однако, с появлением fetch(), который предлагает более простой и понятный интерфейс работы с запросами, необходимость использования XMLHttpRequest существенно снизилась. fetch() предоставляет множество преимуществ, таких как работа с промисами, простая обработка ошибок и более читабельный код.

Базовый синтаксис fetch()

Синтаксис функции fetch() достаточно прост:

  
  let promise = fetch(url, [options]);
  

url: строка, представляющая URL, на который отправляется запрос.

options: необязательный объект, содержащий дополнительные параметры, такие как метод запроса, заголовки, тело запроса и т.д.

Если options отсутствует, запрос просто скачивает содержимое находящееся по url.

Когда вызывается fetch(), браузер сразу же начинает выполнять запрос и возвращает промис, который позволяет работать с результатами запроса по мере их поступления.

Пример GET-запроса

Рассмотрим простой пример, который иллюстрирует, как с помощью fetch() выполнить GET-запрос:

  
  fetch('https://api.example.com/data')
    .then(response => {
      // Проверяем, успешно ли выполнен запрос (статус в диапазоне 200-299)
      if (!response.ok) {
        // Если запрос не успешен, генерируем ошибку с соответствующим статусом
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      // Парсим ответ в формате JSON и возвращаем результат
      return response.json();
    })
    .then(data => {
      // Обрабатываем данные, полученные от сервера
      console.log(data);
    })
    .catch(error => {
      // Обрабатываем ошибки, возникшие при выполнении запроса
      console.error('Fetch error:', error);
    });    
  

В этом примере:

Доступ к телу ответа

После получения ответа на запрос с помощью fetch(), тело ответа не доступно напрямую. Чтобы получить данные, необходимо использовать один из методов объекта Response, который возвращается fetch(). Эти методы позволяют прочитать тело ответа в различных форматах, каждый из которых возвращает промис.

Основные методы для доступа к телу ответа:

response.text(): Читает тело ответа и возвращает его как строку. Этот метод полезен, когда сервер возвращает данные в виде обычного текста, например, HTML или простой текстовый файл.

  
  fetch('https://api.example.com/data.txt')
    .then(response => response.text())
    .then(text => console.log(text))
    .catch(error => console.error('Fetch error:', error));  
  

response.json(): Декодирует тело ответа как JSON и возвращает соответствующий объект JavaScript. Это один из самых распространенных методов, используемых при работе с API, которые возвращают данные в формате JSON.

response.formData(): Возвращает тело ответа как объект FormData, который можно использовать для работы с формами и их полями. Этот метод полезен, если ответ содержит данные, которые можно представить в виде форм.

response.blob(): Возвращает тело ответа как объект Blob, который представляет собой бинарные данные. Это полезно при работе с файлами, такими как изображения, аудио или видео.

response.arrayBuffer(): Возвращает тело ответа как ArrayBuffer, что позволяет работать с низкоуровневыми бинарными данными. Этот метод может быть полезен, если вам нужно работать с данными на уровне байтов.

response.body: Это объект ReadableStream, который позволяет считывать тело ответа по частям. Этот метод полезен для работы с большими данными, которые нужно обрабатывать по мере их получения, например, потоковое видео или аудио.

Вы можете использовать только один метод чтения тела ответа. Если вы уже обработали тело ответа с помощью, например, response.json(), попытка вызвать response.text() приведет к ошибке, поскольку данные уже были обработаны.

Второй аргумент options

Функция fetch() также принимает второй аргумент — объект options, который позволяет настроить запрос:

Пример POST-запроса

Рассмотрим пример, как с помощью fetch() отправить данные на сервер:

  
  // Объект с данными нового пользователя, который мы хотим отправить на сервер
  const newUser = {
    name: 'John Doe',
    email: 'john.doe@example.com',
  };
  
  // Выполняем POST-запрос к указанному URL
  fetch('https://api.example.com/users', {
    method: 'POST', // Устанавливаем метод запроса как POST
    headers: {
      'Content-Type': 'application/json', // Указываем, что отправляемые данные в формате JSON
    },
    // Конвертируем объект newUser в строку JSON, что требуется для отправки данных в формате JSON
    body: JSON.stringify(newUser),
  })
    .then(response => {
      // Проверяем, успешно ли выполнен запрос (статус в диапазоне 200-299)
      if (!response.ok) {
        // Если запрос не успешен, генерируем ошибку с соответствующим статусом
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      // Парсим ответ в формате JSON и возвращаем результат
      return response.json();
    })
    .then(data => {
      // Обрабатываем данные, полученные от сервера
      console.log('User created:', data);
    })
    .catch(error => {
      // Обрабатываем ошибки, возникшие при выполнении запроса
      console.error('Fetch error:', error);
    });    
  

В этом примере отправляем данные нового пользователя на сервер. Устанавливаем метод POST, добавляем заголовок Content-Type: application/json, и конвертируем объект newUser в JSON-строку, которую передаем в тело запроса.

Обработка ошибок

Важно помнить, что fetch() не бросает исключения для HTTP-ошибок, таких как 404 или 500. Исключения возникают только при сетевых ошибках, таких как недоступность сети или сбой DNS. Это означает, что промис, возвращаемый fetch(), будет считаться выполненным (resolved) даже при ошибочных HTTP-статусах (например, 404 Not Found). Однако, если произойдет сетевая ошибка (например, отсутствие интернет-соединения), промис будет отвергнут (rejected).

  
  fetch('https://api.example.com/nonexistent')
    .then(response => {
      // Проверяем, успешно ли выполнен запрос (статус в диапазоне 200-299)
      if (!response.ok) {
        // Если запрос не успешен, генерируем ошибку с соответствующим статусом
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      // Парсим ответ в формате JSON и возвращаем результат
      return response.json();
    })
    .then(data => console.log(data))
    .catch(error => {
      // Обрабатываем ошибки, возникшие при выполнении запроса или сетевые ошибки
      console.error('Fetch error:', error);
    });  
  

В этом примере, если ресурс по указанному URL не найден (404), response.ok будет false, и вызовется throw new Error(), что передаст управление в блок catch. Однако, если возникнет сетевая ошибка, например, сбой DNS, промис fetch() будет автоматически отвергнут, и управление также перейдет в блок catch.

Заключение

fetch() — это мощный инструмент для выполнения HTTP-запросов в JavaScript, который значительно упрощает работу с асинхронными операциями по сравнению с устаревшим XMLHttpRequest. Он делает код более читаемым и предоставляет разработчикам множество возможностей для гибкой настройки запросов и обработки ответов. Изучив основы fetch(), вы сможете легко интегрировать его в свои проекты для взаимодействия с внешними API и серверными приложениями.