Fetch API и async/await

Fetch API представляет собой современный способ работы с HTTP-запросами в JavaScript. Он позволяет отправлять запросы на сервер и получать ответы асинхронно, используя промисы (Promises). Это значительный шаг вперёд по сравнению с устаревшим XMLHttpRequest, который был более громоздким и сложным в использовании.

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

Основной синтаксис

fetch(url, options)
  .then(response => response.json()) // обработка данных
  .catch(error => console.log(error)); // обработка ошибок

Здесь url — это адрес ресурса, к которому делается запрос, а options — это объект, который позволяет настроить запрос (например, метод, заголовки и тело запроса).

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

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

Запрос GET по умолчанию не требует дополнительной настройки, поэтому его можно использовать с минимальными параметрами.

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

Для отправки данных на сервер обычно используется метод POST. В этом случае нужно передать объект options, указывая метод, заголовки и тело запроса.

fetch('https://api.example.com/submit', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ name: 'John', age: 30 })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.log('Ошибка:', error));

В данном примере тело запроса сериализуется в формат JSON, а заголовок указывает серверу, что передаваемые данные имеют формат JSON.

Ответы и обработка ошибок

Метод fetch() не выбрасывает исключений, если сервер возвращает ошибку (например, 404 или 500). Вместо этого он разрешает промис, но статус ответа можно проверить с помощью свойства response.ok или response.status.

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

Здесь проверяется, был ли ответ успешным. Если нет, то выбрасывается ошибка, которая перехватывается в блоке catch.

Async/Await

Async/await — это синтаксический сахар для работы с промисами в JavaScript. Он позволяет писать асинхронный код в более линейном и читаемом виде, избегая “адов” вложенных .then() и .catch().

Синтаксис

Ключевое слово async используется для объявления асинхронных функций, а await позволяет приостановить выполнение кода до получения результата промиса.

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

Здесь запрос к серверу выполняется асинхронно, и код внутри функции не блокирует поток выполнения. await заставляет JavaScript ожидать выполнения промиса, прежде чем продолжить выполнение следующей строки кода.

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

Для запросов с методом POST синтаксис с async/await будет выглядеть так:

async function submitData() {
  try {
    const response = await fetch('https://api.example.com/submit', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ name: 'John', age: 30 })
    });
    if (!response.ok) {
      throw new Error('Ошибка сети');
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log('Ошибка:', error);
  }
}

В этом примере запрос с методом POST отправляется на сервер, а затем обрабатывается аналогично предыдущему примеру, только теперь код более линейный и легче читаемый.

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

Когда используются async/await, ошибки обрабатываются через блоки try/catch, что позволяет более изящно и понятно обрабатывать исключения, чем при использовании промисов напрямую. Это делает код более читаемым и логичным.

Работа с несколькими запросами

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

async function fetchMultipleData() {
  try {
    const [data1, data2] = await Promise.all([
      fetch('https://api.example.com/data1').then(response => response.json()),
      fetch('https://api.example.com/data2').then(response => response.json())
    ]);
    console.log(data1, data2);
  } catch (error) {
    console.log('Ошибка:', error);
  }
}

Здесь Promise.all() позволяет отправить два запроса одновременно и дождаться, пока оба будут выполнены, прежде чем продолжить обработку данных.

Важные моменты

  • CORS (Cross-Origin Resource Sharing): при работе с API важно учитывать ограничения, связанные с политикой CORS. Если сервер не настроен для обработки запросов с других доменов, могут возникнуть проблемы при отправке запросов.
  • Обработка больших данных: для работы с большими объёмами данных можно использовать потоковую передачу данных (streaming). Это позволяет избежать перегрузки памяти, обрабатывая данные по мере их поступления.
  • Тайм-ауты: по умолчанию Fetch API не имеет встроенной поддержки тайм-аутов. Для реализации тайм-аутов нужно использовать дополнительные библиотеки или писать собственный код для отмены запросов через AbortController.

Заключение

Fetch API и async/await значительно упрощают работу с асинхронными запросами в JavaScript, делая код более читаемым и удобным для разработки. Эти инструменты позволяют эффективно обрабатывать запросы, управлять ошибками и работать с множественными параллельными запросами, что делает их незаменимыми для создания современных веб-приложений.