Реализация XMLHttpRequest и fetch() отличается в паре моментов, чтобы обеспечить fetch()лучшее управление запросом и ответом:

  • Промисы, возвращаемые fromfetch()не будут завершаться ошибкой при любом статусе ошибки HTTP (даже HTTP 404 или 500).
  • Это будет успешно разрешено, если статус ok установлен на false.
  • Это произойдет только с ошибкой сети или если запрос не может быть выполнен.
  • По умолчанию fetch() не будет отправлять файлы cookie или учетные данные на сервер.
  • Используя параметр init, вы можете указать, как поступать с файлами cookie и учетными данными, уже сохраненными в клиенте (omit, include, same-origin).
  • С 25 августа 2017 г. спецификация изменила политику учетных данных по умолчанию на same-origin.

использование

Первый аргумент forfetch() — это URL ресурса и, необязательно, второй параметр init (объект с набором атрибутов запроса):

var fetchResponsePromise = fetch(URL [, init] );

Вы можете получить тот же результат, создав объект Request, а затем вызвав fetch()

var request = new Request(URL [, init])
var fetchResponsePromise = fetch(request);

Результатом является Promise, который разрешается в объект Response. Вы можете связать этот вызов с then(), чтобы использовать разрешенный ответ, и catch(), чтобы зафиксировать ошибки в процессе запроса/ответа. Например, это обычный вызов fetch() для извлечения и анализа данных JSON [https://codepen.io/fraigo/pen/GRKdwdR?editors=1111]:

fetch('https://myhost.com/api',{ credentials: 'same-origin' })
  .then(function(response) {
    // use response.text() to continue with plain text
    // verify response checking (response.ok)
    return response.json()
  }).then(function(jsonData) {
    console.log('Parsed JSON', jsonData)
  }).catch(function(ex) {
    console.error('Error', ex.message)
  })

Таким образом, после получения response он преобразуется в объект JSON с помощью response.json().. Затем можно использовать объект JSON jsonData. В случае возникновения какой-либо ошибки исключение ex будет содержать сведения об ошибке. Синтаксис стрелочных функций ES6 еще более понятен:

fetch('https://myhost.com/api',{ credentials: 'same-origin' }) 
  .then(response => response.json())
  .then(jsonData => console.log('Parsed JSON', jsonData))  
  .catch(ex => console.error('Error', ex.message))

Чтобы увидеть разницу, это тот же процесс с использованием XMLHttpRequest [https://codepen.io/fraigo/pen/XWrqyaV?editors=1111].

var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function(){
  if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        try {
          console.log('Response text', httpRequest.responseText); 
          var jsonData=JSON.parse(httpRequest.responseText);
          console.log('Parsed JSON', jsonData);
        } catch (e) {
          console.error("Parse Error", httpRequest.statusText);
        }
      } else {
        console.error("Response Error", httpRequest.statusText);
      }
  }
};
httpRequest.onerror = function(){
   // will fail in HTTP 500 or 404 as well
   console.error("Request Error");
};
httpRequest.open('GET', 'myhost.com/api');
httpRequest.send();

Основные отличия очевидны. Используя XmlHTTPRequest, мы имеем:

  • Множество точек отказа/исключения, различные способы их обнаружения
  • Больше строк кода, не следуйте линейной последовательности
  • Один объектдля управления запросом и ответом

С другой стороны, используя fetch():

  • Обнаружение одной точки отказа в отклонении обещания.
  • Чистый код, затем последовательно
  • Различные объекты для управления запросами и ответами (включая заголовки и тело)

В следующих разделах я покажу вам основные концепции основных компонентов Fetch API: Request, Response и Headers.

Запрос

Основным элементом API-интерфейса Javascript Fetch является файл Request. Основные свойства:

  • .method (например, GET, POST и т. д.)
  • .headers (массив из Header элементов)
  • .credentials (например, «опустить», «того же происхождения», «включить»)
  • .cache (например, по умолчанию, перезагрузить, без кеша)
  • .body (тело запроса)
  • .context (например, аудио, изображение, iframe и т. д.)
  • .mode (например, cors, no-cors, тот же источник, навигация.)
var request = new Request(
  'https://jsonplaceholder.typicode.com/todos/1',
  { 
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded'},
    credentials: 'same-origin',
    body: 'user=John&[email protected]'
  }
);

Заголовки

Кроме того, вы можете манипулировать заголовками HTTP (как в Request, так и в Response) для обычных операций:

  • .append() для создания или добавления нового заголовка (заголовки с одинаковым именем)
  • .delete() для удаления значения заголовка
  • .entries() возвращает итератор для перебора всех заголовков
  • .forEach() помогает перебирать каждый элемент заголовка
  • .get() для получения определенного значения заголовка
  • .has() позволяет проверить, установлено ли имя заголовка
  • .keys() возвращает итератор для перебора всех имен заголовков

В следующем примере мы настраиваем запрос, используя заголовки request.

var myHeaders = new Headers();
myHeaders.append('Content-Type', 'text/json');
myHeaders.append('Authorization', 'Basic QWxhZGRpbjpPcGVuU2VzYW1l');
var myRequest = new Request('https://myhost.com/auth', 
  {headers: myHeaders, method: 'post'})

Кроме того, вы можете получать и управлять заголовками response:

fetch(myRequest).then(function(response) {
  var resHeaders = response.headers;
  if (resHeaders.has('Auth-token')){
     var myToken = resHeaders.get('Auth-token');
     response.text().then(function(textContent) {
       resultMsg.innerText = textContent;
     });
  }
});

Ответ

Наконец, вы можете обработать Response множеством опций и методов:

  • .headers Объект заголовков, связанный с ответом
  • .ok Будетtrue, если ответ был успешным, со статусом HTTP 200-299
  • .status Код состояния HTTP (например, 200 для успеха, 404 не найдено)
  • .statusText Текст, относящийся к коду состояния (например, ОК для 200, Неавторизовано для 401)
  • Все методы Body для управления содержимым ответа:
  • .text()A Обещание получить простые текстовые данные
  • .json()Чтобы получить проанализированные данные JSON в объекте
  • .blob()Для обработки Blob данных (двоичных, необработанных). См. Блоб
  • .arrayBuffer()Чтобы получить массив необработанных байтов. См. ArrayBuffer.

В следующем примере мы получаем двоичные данные в Blob и создаем URL-адрес данных для отображения изображения:

fetch('captcha.png', { cache: 'no-cache' })
  .then(function(response) {
    return response.blob();
   }).then(function(blob) {
     const imageURL = URL.createObjectURL(blob);
     captchaImage.src = imageURL;
   });

Совместимость

Тем, кому нужна обратная совместимость со старыми браузерами без поддержки .fetch(), можно использовать Javascript Fetch API polyfill (https://github.com/github/fetch ).

В некоторых случаях вам также может понадобиться поддержка промисов. Для этого случая доступен Promise полифилл (https://github.com/taylorhakes/promise-polyfill)