В процессе перевода.

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

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

Такая функциональность была ранее достигнута с помощью XMLHttpRequest. Fetch представляет собой лучшую альтернативу, которая может быть легко использована другими технологиями, такими как Service Workers. Fetch также обеспечивает единое логическое место, чтобы определить другие связанные с HTTP такие понятия, как CORS и расширений для HTTP.

Обратите внимание fetch спецификация отличается от jQuery.ajax() в основном двумя способами:

  • Promise возвращенный fetch() не отклонит состояние ошибки HTTP, даже если ответ HTTP 404 или 500.  Вместо этого он будет выполнен нормально (с ok статус установлен в false),  и он будет отклонять только при сбое сети или если что-либо помешало запросу выполнить.
  • По умолчанию, fetch не будет отправлять или получать файлы cookie с сервера, в результате чего запросы без проверки подлинности, если сайт основан на сохранении сессии пользователя (для потправки cookies, параметры доступа должны быть установлены начальные опции).

Оформление запросов

Базовый запрос на получение действительно прост в настройке. Обратите внимание на следующий код:

var myImage = document.querySelector('img');

fetch('flowers.jpg').then(function(response) {
  return response.blob();
}).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

Здесь мы собираем изображение по сети и вставляем его в <img> элемент. Самое простое использование fetch() принимает один аргумент-путь к ресурсу, который вы хотите получить — и возвращает обещание, содержащее ответ (a Response object).

Это просто HTTP-ответ, конечно, а не фактическое изображение. Чтобы извлечь содержимое тела изображения из ответа, мы используем blob() метод  (определяется на Body миксин, которая реализуется как Request и Response objects.)

Примечание: Body миксин имеет подобные методы, чтобы извлечь другие типы body; см. Body раздел подробнее.

An objectURL is then created from the extracted Blob, which is then inserted into the img.

Fetch requests are controlled by the connect-src directive of Content Security Policy rather than the directive of the resources it's retrieving.

Поставляя параметры запроса

Метод fetch() также может принимать второй параметр , init обьект который позволяет вам контролировать различные настройки:

var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

fetch('flowers.jpg', myInit).then(function(response) {
  return response.blob();
}).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

See fetch() for the full options available, and more descriptions.

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

To cause browsers to send a request with credentials included, add credentials: 'include' to the init object you pass to the fetch() method.

fetch('https://example.com', {
  credentials: 'include'  
})

To instead ensure browsers don’t include credentials in the request, use credentials: 'omit'.

fetch('https://example.com', {
  credentials: 'omit'  
})

Убедившись, что выборка была успешной

A fetch() promise will reject with a TypeError when a network error is encountered, although this usually means permission issues or similar — a 404 does not constitute a network error, for example. An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. The code would look something like this:

fetch('flowers.jpg').then(function(response) {
  if(response.ok) {
    return response.blob();
  }
  throw new Error('Network response was not ok.');
}).then(function(myBlob) { 
  var objectURL = URL.createObjectURL(myBlob); 
  myImage.src = objectURL; 
}).catch(function(error) {
  console.log('There has been a problem with your fetch operation: ' + error.message);
});

Поставляя свой собственный объект запроса

Instead of passing a path to the resource you want to request into the fetch() call, you can create a request object using the Request() constructor, and pass that in as a fetch() method argument:

var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg', myInit);

fetch(myRequest).then(function(response) {
  return response.blob();
}).then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});

Request() accepts exactly the same parameters as the fetch() method. You can even pass in an existing request object to create a copy of it:

var anotherRequest = new Request(myRequest, myInit);

This is pretty useful, as request and response bodies are one use only. Making a copy like this allows you to make use of the request/response again, while varying the init options if desired.  The copy must be made before the body is read, and reading the body in the copy will also mark it as read in the original request.

Note: There is also a clone() method that creates a copy. Both methods of creating a copy will fail if the body of the original request or response has already been read, but reading the body of a cloned response or request will not cause it to be marked as read in the original.

Заголовки

The Headers interface allows you to create your own headers object via the Headers() constructor. A headers object is a simple multi-map of names to values:

var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

The same can be achieved by passing an array of arrays or an object literal to the constructor:

myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});

The contents can be queried and retrieved:

console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");
 
console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.get("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
 
myHeaders.delete("X-Custom-Header");
console.log(myHeaders.get("X-Custom-Header")); // [ ]

Some of these operations are only useful in ServiceWorkers, but they provide a much nicer API for manipulating headers.

All of the Headers methods throw a TypeError if a header name is used that is not a valid HTTP Header name. The mutation operations will throw a TypeError if there is an immutable guard (see below). Otherwise they fail silently. For example:

var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://mybank.com");
} catch(e) {
  console.log("Cannot pretend to be a bank!");
}

A good use case for headers is checking whether the content type is correct before you process it further. For example:

fetch(myRequest).then(function(response) {
    var contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then(function(json) { /* process your JSON further */ })
  .catch(function(error) { console.log(error); });

Осторожность

Since headers can be sent in requests and received in responses, and have various limitations about what information can and should be mutable, headers objects have a guard property. This is not exposed to the Web, but it affects which mutation operations are allowed on the headers object.

Possible guard values are:

  • none: default.
  • request: guard for a headers object obtained from a request (Request.headers).
  • request-no-cors: guard for a headers object obtained from a request created with Request.mode no-cors.
  • response: guard for a Headers obtained from a response (Response.headers).
  • immutable: Mostly used for ServiceWorkers; renders a headers object read-only.

Note: You may not append or set a request guarded Headers’ Content-Length header. Similarly, inserting Set-Cookie into a response header is not allowed: ServiceWorkers are not allowed to set cookies via synthesized responses.

Ответ объектов

As you have seen above, Response instances are returned when fetch() promises are resolved.

The most common response properties you'll use are:

  • Response.status — An integer (default value 200) containing the response status code.
  • Response.statusText — A string (default value "OK"),which corresponds to the HTTP status code message.
  • Response.ok — seen in use above, this is a shorthand for checking that status is in the range 200-299 inclusive. This returns a Boolean.

They can also be created programmatically via JavaScript, but this is only really useful in ServiceWorkers, when you are providing a custom response to a received request using a respondWith() method:

var myBody = new Blob();

addEventListener('fetch', function(event) { // ServiceWorker intercepting a fetch
  event.respondWith(
    new Response(myBody, {
      headers: { "Content-Type" : "text/plain" }
    })
  );
});

The Response() constructor takes two optional arguments — a body for the response, and an init object (similar to the one that Request() accepts.)

Note: The static method error() simply returns an error response. Similarly, redirect() returns a response resulting in a redirect to a specified URL. These are also only relevant to Service Workers.

Тело

Both requests and responses may contain body data. A body is an instance of any of the following types:

The Body mixin defines the following methods to extract a body (implemented by both Request and Response). These all return a promise that is eventually resolved with the actual content.

This makes usage of non-textual data much easier than it was with XHR.

Request bodies can be set by passing body parameters:

var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
  method: "POST",
  body: form
});

Both request and response (and by extension the fetch() function), will try to intelligently determine the content type. A request will also automatically set a Content-Type header if none is set in the dictionary.

Функция обнаружения

Fetch API support can be detected by checking for the existence of Headers, Request, Response or fetch() on the Window or Worker scope. For example:

if (self.fetch) {
    // run my fetch request here
} else {
    // do something with XMLHttpRequest?
}

Полифилл

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

Спецификации

Спецификации Статус Комментарий
Fetch Живой стандарт Initial definition

Совместимость браузера

Feature Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Базовая поддержка 42 14 39 (39)
34 (34)[1]
52 (52)[2]
Нет 29
28[1]
10.1
Feature Android Webview Chrome for Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile Chrome for Android
Базовая поддержка 42 42 (Да) Нет ? 10.1 ?

[1] This API is implemented behind a preference.

[2] Prior to Firefox 52, get() only returned the first value in the specified header, with getAll() returning all values. From 52 onwards, get() now returns all values and getAll() has been deleted.

См. также

Метки документа и участники

 Внесли вклад в эту страницу: zhvirblis, Scion, bad4iz
 Обновлялась последний раз: zhvirblis,