Axios или fetch

Как инструмент хождения из браузера на сервер - axios, fetch низкоуровен для такой цели.

Fetch — нативный низкоуровневый JavaScript интерфейс для выполнения HTTP-запросов с использованием обещаний через глобальный метод fetch().

Axios — JavaScript-библиотека, основанная на обещаниях, для выполнения HTTP-запросов.

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

GET запросы JSON данных

Типичная задача во frontend'е — получение JSON данных с сервера. Axios для этого требуется 1 действие, fetch - 2 действия: запрос + вызов метода .json() над результатом запроса.

Fetch

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => response.json())
  .then(json => console.log(json))

Axios

axios.get('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => console.log(response));

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

Axios обрабатывает ошибки логично. Если сервер вернул ответ с HTTP статусом ошибки (например 404 или 500), то обещание будет отвергнуто.

axios.get(url)
  .then(result => console.log('success:', result))
  .catch(error => console.log('error:', error));

Fetch отвергнет обещание только если произошла сетевая ошибка (DNS не разрешил адрес, сервер недоступен, CORS не разрешен). В отстальных случаях ошибки не будет (включая HTTP статусы 404 или 500), поэтому для получения более интуитивного поведения такие ситуации придётся обрабатывать вручную.

fetch(url)
  .then(response => {
    return response.json().then(data => {
      if (response.ok) {
        return data;
      } else {
        return Promise.reject({status: response.status, data});
      }
    });
  })
  .then(result => console.log('success:', result))
  .catch(error => console.log('error:', error));

Некоторые люди скажут: «В чем проблема? Вы запросили данные с сервера, и их получили. И если сервер ответил статусом 404, то это ответ сервера и точка.» На мой взгляд, для разработчика приложений, ответ сервера с кодом ошибки считается таким же исключением как сетевой сбой и должно обрабатываться соответствующим образом.

POST запросы

С axios всё просто, а с fetch уже не так: JSON обязан быть преобразован в строку, а заголовок Content-Type должен указывать, что отправляются JSON данные, иначе сервер будет рассматривать их как строку.

Axios

axios.post('/user', {
  firstName: 'Fred',
  lastName: 'Flintstone'
});

Fetch

fetch('/user', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
});

Базовые значения для запросов

Как вы могли заметить, fetch это явный API, вы ничего не получаете, если об этом не просите. Если используется аутентификация, основанная на сохранении сессии пользователя, то надо явно указывать куку. Если сервер расположен на поддомене, то надо явно прописывать CORS. Эти опции надо прописывать для всех вызовов сервера и у fetch нет механизма для установки значений по-умолчанию, а у axios есть.

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.headers.post['Content-Type'] = 'application/json';

Заключение

Эквивалентный код
Axios

function addUser(details) {
  return axios.post('https://api.example.com/user', details);
}

Fetch

function addUser(details) {
  return fetch('https://api.example.com/user', {
    mode: 'cors',
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify(details),
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'X-XSRF-TOKEN': getCookieValue('XSRF-TOKEN')
    }
  }).then(response => {
    return response.json().then(data => {
      if (response.ok) {
        return data;
      } else {
        return Promise.reject({status: response.status, data});
      }
    });
  });
}

Напрашивается написание функции-обёртку для работы с fetch. Вероятно захочется взять её в следующий проект, а потом сделаеть на её основе свою http библиотеку. Затем сделать её более настраиваемой и получить аналог axios.

Безусловно, fetch очень мощный современный механизм работы с http, но надо признать, что существуют более простые способы решать типовые задачи асинхронного получения ресурсов по сети.


Ссылки:

Похожие записи

HTML атрибуты и DOM свойства

  • Значение HTML атрибута указывает начальное значение;
  • Значение DOM свойства является текущим значением;
  • Атрибуты инициализируют DOM свойства.

Добавить css link и js script динамически

const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css';
link.integrity = 'sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO'; // необязательно
link.crossOrigin = 'anonymous'; // необязательно
document.head.appendChild(link);

const script = document.createElement('script');
script.src = 'https://code.jquery.com/jquery-3.3.1.slim.min.js';
script.integrity = 'sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo'; // необязательно
s...

Не ставить фокус по клику

Проблема заключалась в следующем: когда имеется интерактивный элемент с :focus стилем и вы щелкаете по этому элементу, на нём остаётся focus стиль (outline обводка). У нативной кнопки всё работает as expected, но стоит её добавить любой стиль и, как побочный эффект, меняется её поведение.