Поиск по сайту:

Учебник по Fetch API


Fetch — это новый API на основе промисов, который позволяет нам выполнять запросы Ajax без всей суеты, связанной с XMLHttpRequest. Как вы увидите в этом посте, Fetch очень прост в использовании и работе, а также значительно упрощает получение ресурсов из API. Кроме того, теперь он поддерживается во всех современных браузерах, поэтому использовать Fetch не составляет труда.

Получить запросы

Давайте продемонстрируем простой запрос GET, выполнив GET некоторые фиктивные данные из JSONPlaceholder API:

fetch('https://jsonplaceholder.typicode.com/users')
  .then(res => res.json())
  .then(res => res.map(user => user.username))
  .then(userNames => console.log(userNames));

И на выходе будет такой массив имен пользователей:

["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]

Учитывая, что мы ожидаем ответ в формате JSON, нам сначала нужно вызвать метод json(), чтобы преобразовать объект Response в объект, с которым мы можем взаимодействовать. Можно было бы использовать text(), если вместо этого мы ожидали ответа в формате XML.

Размещать, размещать и удалять запросы

Чтобы делать запросы, отличные от GET, передайте объект в качестве второго аргумента вызова выборки с используемым методом, а также любые необходимые заголовки и тело запроса:

const myPost = {
  title: 'A post about true facts',
  body: '42',
  userId: 2
}

const options = {
  method: 'POST',
  body: JSON.stringify(myPost),
  headers: {
    'Content-Type': 'application/json'
  }
};

fetch('https://jsonplaceholder.typicode.com/posts', options)
  .then(res => res.json())
  .then(res => console.log(res));

JSONPlaceholder отправляет нам отправленные данные обратно с прикрепленным идентификатором:

Object {
  body: 42,
  id: 101,
  title: "A post about true facts",
  userId: 2
}

Вы заметите, что тело запроса должно быть строковым. Другие методы, которые вы можете использовать для вызовов выборки: DELETE, PUT, HEAD и OPTIONS.

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

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

К счастью, объект ответа на вызов fetch имеет свойство ok, которое может принимать значение true или false в зависимости от успешности запроса. Затем вы можете использовать Promise.reject(), если ok имеет значение false:

fetch('https://jsonplaceholder.typicode.com/postsZZZ', options)
  .then(res => {
    if (res.ok) {
      return res.json();
    } else {
      return Promise.reject({ status: res.status, statusText: res.statusText });
    }
  })
  .then(res => console.log(res))
  .catch(err => console.log('Error, with message:', err.statusText));

В приведенном выше примере наше обещание будет отклонено, потому что мы вызываем конечную точку, которая не существует. Сцепленный вызов catch будет выполнен, и будет выведено следующее:

"Error, with message: Not Found"

Извлечь + асинхронно/ожидание

Поскольку Fetch — это API на основе обещаний, использование функций async — отличный способ сделать ваш код еще более простым для понимания и синхронным. Вот, например, функция async/await, которая выполняет простой запрос GET и извлекает имена пользователей из возвращенного ответа JSON, а затем записывает результат в консоль:

async function fetchUsers(endpoint) {
  const res = await fetch(endpoint);
  let data = await res.json();

  data = data.map(user => user.username);

  console.log(data);
}

fetchUsers('https://jsonplaceholder.typicode.com/users');

Или вы можете просто вернуть обещание из вашей функции async/await, и тогда у вас будет возможность продолжать цепочку вызовов then после вызова функции:

async function fetchUsers(endpoint) {
  const res = await fetch(endpoint);
  const data = await res.json();

  return data;
}

fetchUsers('https://jsonplaceholder.typicode.com/users')
  .then(data => {
    console.log(data.map(user => user.username));
  });

Вызов json() возвращает обещание, поэтому в приведенном выше примере, когда мы возвращаем данные в асинхронной функции, мы возвращаем обещание.

И опять же, вы также можете выдать ошибку, если ответ ok ложный, и поймать ошибку, как обычно, в вашей цепочке промисов:

async function fetchUsers(endpoint) {
  const res = await fetch(endpoint);

  if (!res.ok) {
    throw new Error(res.status); // 404
  }

  const data = await res.json();
  return data;
}

fetchUsers('https://jsonplaceholder.typicode.com/usersZZZ')
  .then(data => {
    console.log(data.map(user => user.website));
  })
  .catch(err => console.log('Ooops, error', err.message));
Ooops, error 404

Полифиллы

  • Если вам нужна поддержка старых браузеров, таких как Internet Explorer 11, вам потребуется использовать полифилл Fetch, подобный этому, из Github.
  • Если вам нужно использовать Fetch в Node.js, два самых популярных варианта — это node-fetch.

Поддержка браузера

caniuse.com.