Введение в выборку()

fetch() позволяет отправлять сетевые запросы, аналогичные XMLHttpRequest (XHR). Основное отличие состоит в том, что API-интерфейс Fetch использует Promises, который имеет более простой API, позволяющий избежать сложных обратных вызовов в API XMLHttpRequest.

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

  • Хром: 42.
  • Край: 14.
  • Фаерфокс: 39.
  • Сафари: 10.1.

Источник

Если вы никогда раньше не использовали Promises , ознакомьтесь со статьей «Введение в промисы JavaScript» .

Базовый запрос на получение

Вот пример, реализованный с помощью XMLHttpRequest , а затем с помощью fetch . Мы хотим запросить URL-адрес, получить ответ и проанализировать его как JSON.

XMLHttpRequest

Для XMLHttpRequest требуются два прослушивателя для обработки случаев успеха и ошибки, а также вызов open() и send() . Пример из документации MDN .

function reqListener () {
  const data = JSON.parse(this.responseText);
  console.log(data);
}

function reqError (err) {
  console.log('Fetch Error :-S', err);
}

const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();

Принести

Наш запрос на получение выглядит следующим образом:

fetch('./api/some.json')
  .then(response => {
    if (response.status !== 200) {
      console.log(`Looks like there was a problem. Status Code: ${response.status}`);

      return;
    }

    // Examine the text in the response
    response.json().then(function(data) {
      console.log(data);
    });
  })
  .catch(err => {
    console.log('Fetch Error :-S', err);
  });

Запросу fetch() требуется только один вызов, чтобы выполнить ту же работу, что и в примере XHR. Чтобы обработать ответ, мы сначала проверяем, что статус ответа равен 200, а затем анализируем ответ как JSON. Ответом на запрос fetch() является объект Stream , а это означает, что после вызова метода json() возвращается обещание. Поток происходит асинхронно.

Метаданные ответа

В предыдущем примере показано состояние объекта Response и способ анализа ответа в формате JSON. Вот как обрабатывать другие метаданные, к которым вам может понадобиться доступ, например заголовки:

fetch('users.json').then(response => {
  console.log(response.headers.get('Content-Type'));
  console.log(response.headers.get('Date'));

  console.log(response.status);
  console.log(response.statusText);
  console.log(response.type);
  console.log(response.url);
});

Типы ответов

Когда мы делаем запрос на выборку, ответу будет присвоен тип response.type « basic », « cors » или « opaque ». Эти types показывают, откуда взялся ресурс, и вы можете использовать их, чтобы определить, как обращаться с объектом ответа.

Когда браузер запрашивает ресурс из того же источника, ответ имеет basic тип с ограничениями на то, что вы можете просмотреть из ответа.

Если запрос делается для ресурса в другом источнике, и этот источник возвращает заголовки COR , тогда тип — cors . Ответы cors аналогичны basic ответам, но они ограничивают заголовки, которые вы можете просматривать, Cache-Control , Content-Language , Content-Type , Expires , Last-Modified и Pragma .

opaque ответы приходят из другого источника, который не возвращает заголовки CORS. При непрозрачном ответе мы не сможем прочитать возвращенные данные или просмотреть статус запроса, то есть вы не сможете проверить, был ли запрос успешным.

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

  • same-origin успешен только для запросов на активы из того же источника и отклоняет все остальные запросы.
  • cors позволяет запрашивать активы из того же и других источников, которые возвращают соответствующие заголовки COR.
  • cors-with-forced-preflight выполняет предполетную проверку перед выполнением любого запроса.
  • no-cors предназначен для отправки запросов к другим источникам, которые не имеют заголовков CORS и приводят к opaque ответу, но, как уже говорилось, на данный момент это невозможно в глобальной области видимости окна.

Чтобы определить режим, добавьте объект параметров в качестве второго параметра в запросе fetch и определите режим в этом объекте:

fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
  .then(response => response.text())
  .then(text => {
    console.log('Request successful', text);
  })
  .catch(error => {
    log('Request failed', error)
  });

Цепочка обещаний

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

Если вы работаете с API JSON, вам необходимо проверять статус и анализировать JSON для каждого ответа. Вы можете упростить свой код, определив статус и анализ JSON в отдельных функциях, которые возвращают обещания, и использовать запрос на выборку для обработки только окончательных данных и случая ошибки.

function status (response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response)
  } else {
    return Promise.reject(new Error(response.statusText))
  }
}

function json (response) {
  return response.json()
}

fetch('users.json')
  .then(status)
  .then(json)
  .then(data => {
    console.log('Request succeeded with JSON response', data);
  }).catch(error => {
    console.log('Request failed', error);
  });

В этом примере определяется функция status , которая проверяет response.status и возвращает либо разрешенное обещание как Promise.resolve() , либо отклоненное обещание как Promise.reject() . Это первый метод, вызываемый в цепочке fetch() .

Если промис разрешается, сценарий затем вызывает метод json() , который возвращает второй промис из вызова response.json() и создает объект, содержащий проанализированный JSON. Если синтаксический анализ завершается неудачей, обещание отклоняется и выполняется оператор catch.

Эта структура позволяет вам использовать логику для всех ваших запросов на выборку, что упрощает обслуживание, чтение и тестирование кода.

POST-запрос

Иногда веб-приложению необходимо вызвать API с помощью метода POST и включить некоторые параметры в тело запроса. Для этого установите параметры method и body в опциях fetch() :

fetch(url, {
    method: 'post',
    headers: {
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    body: 'foo=bar&lorem=ipsum'
  })
  .then(json)
  .then(data => {
    console.log('Request succeeded with JSON response', data);
  })
  .catch(error => {
    console.log('Request failed', error);
  });

Отправка учетных данных с запросом на получение

Чтобы выполнить запрос на выборку с учетными данными, такими как файлы cookie, установите для credentials запроса значение "include" :

fetch(url, {
  credentials: 'include'
})