diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
commit | 074785cea106179cb3305637055ab0a009ca74f2 (patch) | |
tree | e6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/api/fetch_api | |
parent | da78a9e329e272dedb2400b79a3bdeebff387d47 (diff) | |
download | translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2 translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip |
initial commit
Diffstat (limited to 'files/ru/web/api/fetch_api')
-rw-r--r-- | files/ru/web/api/fetch_api/cross-global_fetch_usage/index.html | 33 | ||||
-rw-r--r-- | files/ru/web/api/fetch_api/index.html | 102 | ||||
-rw-r--r-- | files/ru/web/api/fetch_api/using_fetch/index.html | 488 |
3 files changed, 623 insertions, 0 deletions
diff --git a/files/ru/web/api/fetch_api/cross-global_fetch_usage/index.html b/files/ru/web/api/fetch_api/cross-global_fetch_usage/index.html new file mode 100644 index 0000000000..ec05253d7f --- /dev/null +++ b/files/ru/web/api/fetch_api/cross-global_fetch_usage/index.html @@ -0,0 +1,33 @@ +--- +title: Cross-global fetch usage +slug: Web/API/Fetch_API/Cross-global_fetch_usage +translation_of: Web/API/Fetch_API/Cross-global_fetch_usage +--- +<p class="summary">Эта статья объясняет крайний случай, который случается с fetch (и потенциально с другими API, предоставляющими такой же способ получения данных). Когда cross-origin fetch, включающий относительный URL, инициируется из {{htmlelement("iframe")}}, относительный URL может использовать текущий глобальный location вместо того что задается в iframe.</p> + +<h2 id="Крайний_случай">Крайний случай</h2> + +<p>Многие сайты никогда не столкнутся с таким поведением. Чтобы увидеть его:</p> + +<ul> + <li>Вам понадобится same-origin iframe</li> + <li>Этот same-origin iframe должен располагаться с другим base URL</li> + <li>Вы должны использовать функцию fetch cross-global, т. е. <code>frame.contentWindow.fetch()</code></li> + <li>Переданный в fetch URL должен быть относительным</li> +</ul> + +<h2 id="Проблема">Проблема</h2> + +<p>В прошлом мы разрешали относительный URL адрес вместо текущего глобального, для примера:</p> + +<pre class="brush: js">let absolute = new URL(relative, window.location.href)</pre> + +<p>Это не проблема как таковая. Просто разные API, демонстрирующие такое поведение, делали его несовместимым с поведением, определенным в спецификации, что может привести к проблемам в дальнейшем.</p> + +<h2 id="Решение">Решение</h2> + +<p>В Firefox 60 и далее, Mozilla сопоставляет относительный URL с глобальным, которой принадлежит используемой функции <code>fetch()</code> (смотри {{bug(1432272)}}). Таким образом в случае описанном выше, он разрешается в зависимости от расположения iframe:</p> + +<pre class="brush: js">let absolute = new URL(relative, frame.contentWindow.location.href)</pre> + +<p>Ведется много дискуссий о том, как привести новые спецификации в соотвествие с этим изменением поведения, для того чтобы уменьшить возможные проблемы в будущем.</p> diff --git a/files/ru/web/api/fetch_api/index.html b/files/ru/web/api/fetch_api/index.html new file mode 100644 index 0000000000..cb3917dcf8 --- /dev/null +++ b/files/ru/web/api/fetch_api/index.html @@ -0,0 +1,102 @@ +--- +title: Fetch API +slug: Web/API/Fetch_API +tags: + - API + - Fetch + - Response + - XMLHttpRequest + - request + - Главная + - Справка + - Экспериментальная +translation_of: Web/API/Fetch_API +--- +<p>{{DefaultAPISidebar("Fetch API")}}</p> + +<p>Fetch API предоставляет интерфейс для получения ресурсов (в том числе по сети). Он покажется знакомым любому, кто использовал {{DOMxRef("XMLHttpRequest")}}, но новый API является более мощным и гибким набором функций.</p> + +<h2 id="Oпределения_и_использование">Oпределения и использование</h2> + +<p>Fetch обеспечивает обобщенное определение объектов {{DOMxRef("Request")}} и {{DOMxRef("Response")}} (и других вещей, связанных с сетевыми запросами). Это позволит им использоваться везде, где необходимо в будущем, в том числе и для service workers, Cache API и других подобных технологий, которые обрабатывают или изменяют запросы (requests) и ответы (responses), а так же в любых других случаях, которые могут потребовать от вас генерировать свой собственный ответ программно.</p> + +<p>Это также предоставляет определение в отношение таких понятий, как CORS и семантика заголовков HTTP origin, заменяя их обособленные определения где бы то ни было.</p> + +<p>Чтобы создать запрос и получить данные, используется метод {{DOMxRef("GlobalFetch.fetch")}}. Он реализован во множестве интерфейсов, в том числе в {{DOMxRef("Window")}} и {{DOMxRef("WorkerGlobalScope")}}. Это позволяет использовать его практически в любом контексте для получения данных.</p> + +<p>Метод <code>fetch()</code> принимает один обязательный аргумент — путь к данным, которые вы хотите получить. Он возвращает promise, который разрешается в ({{DOMxRef("Response")}}) независимо от того, был ли запрос удачным. Вы можете также передать во втором аргументе необязательный объект с указанием опций (см. {{DOMxRef("Request")}}.)</p> + +<p>Как только {{DOMxRef("Response")}} выполнится успешно, становятся доступными несколько методов для определения тела контента и, как его содержимое олжно быть обработано (см. {{DOMxRef("Body")}}.)</p> + +<p>Вы можете создавать запрос и ответ непосредственно, используя конструкторы {{DOMxRef("Request.Request","Request()")}} и {{DOMxRef("Response.Response","Response()")}}, но маловероятно, что в этом есть необходимость. Напротив, более вероятно, что они будут созданы как результат работы другого API (например, {{DOMxRef("FetchEvent.respondWith")}} в service workers.)</p> + +<h3 id="Отличия_от_jQuery">Отличия от jQuery</h3> + +<p>Спецификации <code>fetch()</code> отличаются от <code>jQuery.ajax()</code> тремя основными способами:</p> + +<ul> + <li> + <p>Обещание, возвращенное из <code>fetch()</code>, <strong>не будет отвергнуто при статусе ошибки HTTP</strong>, даже если ответ является HTTP <code>404</code> или <code>500</code>. Вместо этого, оно будет разрешаться нормально (со статусом <code>ok</code> установленным в <code>false</code>), и будет отклоняться только при сбое в сети или если что-то помешало завершению запроса.</p> + </li> + <li> + <p><code>fetch() </code>может получать межсайтовые куки-файлы; таким образом вы можете установить межсайтовую сессию используя <code>fetch</code>.</p> + </li> + <li><code>fetch()</code> не будет посылать куки-файлы, если только не указано <code>credentials: 'same-origin'</code>.</li> +</ul> + +<div class="note"><strong>Заметка</strong>: узнайте больше об использовании Fetch API на <a href="/en-US/docs/Web/API/Fetch_API/Using_Fetch">Using Fetch</a> и изучите концепции на <a href="/en-US/docs/Web/API/Fetch_API/Basic_concepts">Fetch basic concepts</a>.</div> + +<h3 id="Прерывание_выборки">Прерывание выборки</h3> + +<p>Браузеры начали добавлять экспериментальную поддержку для {{domxref("AbortController")}} и {{domxref("AbortSignal")}} интерфейсов (aka The Abort API), которые позволяют прерывать операции, такие как Fetch и XHR, если они еще не завершены. Подробности смотрите на страницах интерфейсов.</p> + +<h2 id="Fetch_интерфейсы">Fetch интерфейсы</h2> + +<dl> + <dt>{{DOMxRef("GlobalFetch")}}</dt> + <dd>Содержит метод <code>fetch()</code>, используемый для получения ресурсов.</dd> + <dt>{{DOMxRef("Headers")}}</dt> + <dd>Представляет заголовки запроса/ответа, позволяет запрашивать данные и выполнять различные действия в зависимости от результата.</dd> + <dt>{{DOMxRef("Request")}}</dt> + <dd>Запрашивает ресурс.</dd> + <dt>{{DOMxRef("Response")}}</dt> + <dd>Представляет ответ на запрос.</dd> +</dl> + +<h2 id="Fetch_примесь">Fetch примесь</h2> + +<dl> + <dt>{{DOMxRef("Body")}}</dt> + <dd>Предоставляет методы, относящиеся к телу запроса/ответа, позволяя вам определять content-type и то, как ответ должен быть обработан.</dd> +</dl> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификация</th> + <th scope="col">Статус</th> + <th scope="col">Комментарий</th> + </tr> + <tr> + <td>{{SpecName('Fetch')}}</td> + <td>{{Spec2('Fetch')}}</td> + <td>Изначальное определение</td> + </tr> + </tbody> +</table> + +<h2 id="Браузерная_совместимость">Браузерная совместимость</h2> + +<p>{{Compat("api.WindowOrWorkerGlobalScope.fetch")}}</p> + +<h2 id="Смотрите_также">Смотрите также</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/ServiceWorker_API">ServiceWorker API</a></li> + <li><a href="/en-US/docs/Web/HTTP/Access_control_CORS">HTTP access control (CORS)</a></li> + <li><a href="/en-US/docs/Web/HTTP">HTTP</a></li> + <li><a href="https://github.com/github/fetch">Fetch полифил</a></li> + <li><a href="/en-US/docs/Web/API/Fetch_API/Basic_concepts">Fetch базовые понятия</a></li> +</ul> diff --git a/files/ru/web/api/fetch_api/using_fetch/index.html b/files/ru/web/api/fetch_api/using_fetch/index.html new file mode 100644 index 0000000000..f123f02792 --- /dev/null +++ b/files/ru/web/api/fetch_api/using_fetch/index.html @@ -0,0 +1,488 @@ +--- +title: Использование Fetch +slug: Web/API/Fetch_API/Using_Fetch +translation_of: Web/API/Fetch_API/Using_Fetch +--- +<p><a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a> предоставляет интерфейс JavaScript для работы с запросами и ответами HTTP. Он также предоставляет глобальный метод {{domxref("GlobalFetch.fetch","fetch()")}}, который позволяет легко и логично получать ресурсы по сети асинхронно.</p> + +<p>Подобная функциональность ранее достигалась с помощью {{domxref("XMLHttpRequest")}}. Fetch представляет собой лучшую альтернативу, которая может быть легко использована другими технологиями, такими как {{domxref("ServiceWorker_API", "Service Workers")}}. Fetch также обеспечивает единое логическое место для определения других связанных с HTTP понятий, такие как CORS и расширения для HTTP.</p> + +<p>Обратите внимание, <code>fetch</code> спецификация отличается от <code>jQuery.ajax()</code> в основном в двух пунктах:</p> + +<ul> + <li>Promise возвращаемый вызовом <code>fetch()</code> <strong>не перейдет в состояние "отклонено" из-за ответа HTTP, который считается ошибкой</strong>, даже если ответ HTTP 404 или 500. Вместо этого, он будет выполнен нормально (с значением false в статусе <code>ok</code> ) и будет отклонён только при сбое сети или если что-то помешало запросу выполниться.</li> + <li>По умолчанию, <code>fetch</code> <strong>не будет отправлять или получать cookie файлы </strong>с сервера, в результате чего запросы будут осуществляться без проверки подлинности, что приведёт<span class="tlid-translation translation" lang="ru"><span title=""> к неаутентифицированным запросам</span></span>, если сайт полагается на проверку пользовательской сессии (для отправки cookie файлов в аргументе <a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters">init options</a> должно быть задано значение свойства <em>credentials</em> отличное от значения по умолчанию <code>omit</code>).</li> +</ul> + +<div class="blockIndicator note"> +<p>25 августа 2017 г. в спецификации изменилось значение по умолчанию свойства <em>credentials</em> на <code>same-origin</code>. Firefox применяет это изменение с версии 61.0b13.</p> +</div> + +<p>Базовый запрос на получение данных действительно прост в настройке. Взгляните на следующий код:</p> + +<pre>fetch('http://example.com/movies.json') + .then((response) => { + return response.json(); + }) + .then((data) => { + console.log(data); + });</pre> + +<p>Здесь мы забираем JSON файл по сети и выводим его содержимое в консоль. Самый простой способ использования <code>fetch()</code> заключается в вызове этой функии с одним аргументом — строкой, содержащей путь к ресурсу, который вы хотите получить — которая возвращает promise, содержащее ответ (объект {{domxref("Response")}}).</p> + +<p>Конечно, это просто HTTP-ответ, а не фактический JSON. Чтобы извлечь содержимое тела JSON из ответа, мы используем {{domxref("Body.json","json()")}} метод (определён миксином {{domxref("Body")}}, который реализован в объектах {{domxref("Request")}} и {{domxref("Response")}}.)</p> + +<div class="note"> +<p><strong>Примечание</strong>: Миксин Body имеет подобные методы для извлечения других типов контента; см. раздел {{anch("Тело")}}.</p> +</div> + +<p>Fetch-запросы контролируются посредством директивы <code>connect-src</code> (<a href="/en-US/docs/Security/CSP/CSP_policy_directives">Content Security Policy</a>), а не директивой извлекаемых ресурсов.</p> + +<h3 id="Установка_параметров_запроса">Установка параметров запроса</h3> + +<p>Метод <code>fetch()</code> может принимать второй параметр - обьект <code>init</code>, который позволяет вам контролировать различные настройки:</p> + +<pre class="brush: js">// Пример отправки POST запроса: +async function postData(url = '', data = {}) { + // Default options are marked with * + const response = await fetch(url, { + method: 'POST', // *GET, POST, PUT, DELETE, etc. + mode: 'cors', // no-cors, *cors, same-origin + cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached + credentials: 'same-origin', // include, *same-origin, omit + headers: { + 'Content-Type': 'application/json' + // 'Content-Type': 'application/x-www-form-urlencoded', + }, + redirect: 'follow', // manual, *follow, error + referrerPolicy: 'no-referrer', // no-referrer, *client + body: JSON.stringify(data) // body data type must match "Content-Type" header + }); + return await response.json(); // parses JSON response into native JavaScript objects +} + +postData('https://example.com/answer', { answer: 42 }) + .then((data) => { + console.log(data); // JSON data parsed by `response.json()` call + });</pre> + +<p>С подробным описанием функции и полным списком параметров вы можете ознакомиться на странице {{domxref("GlobalFetch.fetch","fetch()")}}.</p> + +<h3 id="Отправка_запроса_с_учётными_данными">Отправка запроса с учётными данными</h3> + +<p>Чтобы браузеры могли отправлять запрос с учётными данными (даже для cross-origin запросов), добавьте <code>credentials: 'include'</code> в объект <code>init</code>, передаваемый вами в метод <code>fetch()</code>:</p> + +<pre class="brush: js"><code>fetch('https://example.com', { + credentials: 'include' +})</code></pre> + +<p>Если вы хотите отправлять запрос с учетными данными только если URL принадлежит одному источнику (origin) что и вызывающий его скрипт, добавьте <code>credentials: 'same-origin'</code>.</p> + +<pre><code>// Вызывающий скрипт принадлежит источнику 'https://example.com' + +fetch('https://example.com', { + credentials: 'same-origin' +})</code></pre> + +<p>Напротив, чтобы быть уверенным, что учётные данные не передаются с запросом, используйте <code>credentials: 'omit'</code>:</p> + +<pre class="brush: js"><code>fetch('https://example.com', { + credentials: 'omit' +})</code></pre> + +<h3 id="Отправка_данных_в_формате_JSON">Отправка данных в формате JSON</h3> + +<p>При помощи {{domxref("GlobalFetch.fetch","fetch()")}} можно отправлять POST-запросы в формате JSON.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> url <span class="operator token">=</span> <span class="string token">'https://example.com/profile'</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> data <span class="operator token">=</span> <span class="punctuation token">{</span> username<span class="punctuation token">:</span> <span class="string token">'example'</span> <span class="punctuation token">}</span><span class="punctuation token">;</span> + +<span class="keyword token">try</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span>url<span class="punctuation token">,</span> <span class="punctuation token">{</span> + method<span class="punctuation token">:</span> <span class="string token">'POST'</span><span class="punctuation token">,</span> <span class="comment token">// или 'PUT'</span> + body<span class="punctuation token">:</span> <span class="constant token">JSON</span><span class="punctuation token">.</span><span class="function token">stringify</span><span class="punctuation token">(</span>data<span class="punctuation token">)</span><span class="punctuation token">,</span> <span class="comment token">// данные могут быть 'строкой' или {объектом}!</span> + headers<span class="punctuation token">:</span> <span class="punctuation token">{</span> + <span class="string token">'Content-Type'</span><span class="punctuation token">:</span> <span class="string token">'application/json'</span> + <span class="punctuation token">}</span> + <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">const</span> json <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">json</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'Успех:'</span><span class="punctuation token">,</span> <span class="constant token">JSON</span><span class="punctuation token">.</span><span class="function token">stringify</span><span class="punctuation token">(</span>json<span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>error<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">error</span><span class="punctuation token">(</span><span class="string token">'Ошибка:'</span><span class="punctuation token">,</span> error<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Загрузка_файла_на_сервер">Загрузка файла на сервер</h3> + +<p>На сервер можно загрузить файл, используя комбинацию HTML-элемента <code><input type="file" /></code>, {{domxref("FormData.FormData","FormData()")}} и {{domxref("WindowOrWorkerGlobalScope/fetch","fetch()")}}.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> formData <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">FormData</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> fileField <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">'input[type="file"]'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +formData<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'username'</span><span class="punctuation token">,</span> <span class="string token">'abc123'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +formData<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'avatar'</span><span class="punctuation token">,</span> fileField<span class="punctuation token">.</span>files<span class="punctuation token">[</span><span class="number token">0</span><span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +<span class="keyword token">try</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span><span class="string token">'https://example.com/profile/avatar'</span><span class="punctuation token">,</span> <span class="punctuation token">{</span> + method<span class="punctuation token">:</span> <span class="string token">'PUT'</span><span class="punctuation token">,</span> + body<span class="punctuation token">:</span> formData + <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">const</span> result <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">json</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'Успех:'</span><span class="punctuation token">,</span> <span class="constant token">JSON</span><span class="punctuation token">.</span><span class="function token">stringify</span><span class="punctuation token">(</span>result<span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>error<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">error</span><span class="punctuation token">(</span><span class="string token">'Ошибка:'</span><span class="punctuation token">,</span> error<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Загрузка_нескольких_файлов_на_сервер">Загрузка нескольких файлов на сервер</h3> + +<p>На сервер можно загрузить несколько файлов, используя комбинацию HTML-элемента <code><input type="file" multiple /></code>, {{domxref("FormData.FormData","FormData()")}} и {{domxref("WindowOrWorkerGlobalScope/fetch","fetch()")}}.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> formData <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">FormData</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> photos <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">'input[type="file"][multiple]'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +formData<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'title'</span><span class="punctuation token">,</span> <span class="string token">'Мой отпуск в Вегасе'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">for</span> <span class="punctuation token">(</span><span class="keyword token">let</span> i <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> i <span class="operator token"><</span> photos<span class="punctuation token">.</span>files<span class="punctuation token">.</span>length<span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + formData<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'photos'</span><span class="punctuation token">,</span> photos<span class="punctuation token">.</span>files<span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +<span class="keyword token">try</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span><span class="string token">'https://example.com/posts'</span><span class="punctuation token">,</span> <span class="punctuation token">{</span> + method<span class="punctuation token">:</span> <span class="string token">'POST'</span><span class="punctuation token">,</span> + body<span class="punctuation token">:</span> formData + <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">const</span> result <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">json</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'Успех:'</span><span class="punctuation token">,</span> <span class="constant token">JSON</span><span class="punctuation token">.</span><span class="function token">stringify</span><span class="punctuation token">(</span>result<span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>error<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">error</span><span class="punctuation token">(</span><span class="string token">'Ошибка:'</span><span class="punctuation token">,</span> error<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Обработка_текстового_файла_построчно">Обработка текстового файла построчно</h3> + +<p>Фрагменты данных, получаемые из ответа, не разбиваются на строки автоматически (по крайней мере с достаточной точностью) и представляют собой не строки, а объекты {{jsxref("Uint8Array","Uint8Array")}}. Если вы хотите загрузить текстовый файл и обрабатывать его по мере загрузки построчно, то на вас самих ложится груз ответственности за обработку всех упомянутых моментов. Как пример, далее представлен один из способов подобной обработки с помощью создания построчного итератора (для простоты приняты следующие допущения: текст приходит в кодировке UTF-8 и ошибки получения не обрабатываются).</p> + +<pre class="brush: js">async function* makeTextFileLineIterator(fileURL) { + const utf8Decoder = new TextDecoder("utf-8"); + let response = await fetch(fileURL); + let reader = response.body.getReader(); + let {value: chunk, done: readerDone} = await reader.read(); + chunk = chunk ? utf8Decoder.decode(chunk) : ""; + + let re = /\n|\r|\r\n/gm; + let startIndex = 0; + let result; + + for (;;) { + let result = re.exec(chunk); + if (!result) { + if (readerDone) { + break; + } + let remainder = chunk.substr(startIndex); + ({value: chunk, done: readerDone} = await reader.read()); + chunk = remainder + (chunk ? utf8Decoder.decode(chunk) : ""); + startIndex = re.lastIndex = 0; + continue; + } + yield chunk.substring(startIndex, result.index); + startIndex = re.lastIndex; + } + if (startIndex < chunk.length) { + //последняя строка не имеет символа перевода строки в конце + yield chunk.substr(startIndex); + } +} + +for await (let line of makeTextFileLineIterator(urlOfFile)) { + processLine(line); +}</pre> + +<h3 id="Проверка_успешности_запроса">Проверка успешности запроса</h3> + +<p>В методе {{domxref("GlobalFetch.fetch","fetch()")}} promise будет отклонён (reject) с {{jsxref("TypeError")}}, когда случится ошибка сети или не будет сконфигурирован CORS на стороне запрашиваемого сервера, хотя обычно это означает проблемы доступа или аналогичные — для примера, 404 не является сетевой ошибкой. Для достоверной проверки успешности <code>fetch()</code> будет включать проверку того, что promise успешен (resolved), затем проверку того, что значение свойства {{domxref("Response.ok")}} является true. Код будет выглядеть примерно так:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">try</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span><span class="string token">'flowers.jpg'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span><span class="operator token">!</span>response<span class="punctuation token">.</span>ok<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">throw</span> <span class="keyword token">new</span> <span class="class-name token">Error</span><span class="punctuation token">(</span><span class="string token">'Ответ сети был не ok.'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + <span class="keyword token">const</span> myBlob <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">blob</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">const</span> objectURL <span class="operator token">=</span> <span class="constant token">URL</span><span class="punctuation token">.</span><span class="function token">createObjectURL</span><span class="punctuation token">(</span>myBlob<span class="punctuation token">)</span><span class="punctuation token">;</span> + myImage<span class="punctuation token">.</span>src <span class="operator token">=</span> objectURL<span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>error<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'Возникла проблема с вашим fetch запросом: '</span><span class="punctuation token">,</span> error<span class="punctuation token">.</span>message<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Составление_своего_объекта_запроса">Составление своего объекта запроса</h3> + +<p>Вместо передачи пути ресурса, который вы хотите запросить вызовом <code>fetch()</code>, вы можете создать объект запроса, используя конструктор {{domxref("Request.Request","Request()")}}, и передать его в <code>fetch()</code> аргументом:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> myHeaders <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Headers</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +<span class="keyword token">const</span> myInit <span class="operator token">=</span> <span class="punctuation token">{</span> + method<span class="punctuation token">:</span> <span class="string token">'GET'</span><span class="punctuation token">,</span> + headers<span class="punctuation token">:</span> myHeaders<span class="punctuation token">,</span> + mode<span class="punctuation token">:</span> <span class="string token">'cors'</span><span class="punctuation token">,</span> + cache<span class="punctuation token">:</span> <span class="string token">'default'</span> +<span class="punctuation token">}</span><span class="punctuation token">;</span> + +<span class="keyword token">const</span> myRequest <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Request</span><span class="punctuation token">(</span><span class="string token">'flowers.jpg'</span><span class="punctuation token">,</span> myInit<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span>myRequest<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> myBlob <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">blob</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> objectURL <span class="operator token">=</span> <span class="constant token">URL</span><span class="punctuation token">.</span><span class="function token">createObjectURL</span><span class="punctuation token">(</span>myBlob<span class="punctuation token">)</span><span class="punctuation token">;</span> +myImage<span class="punctuation token">.</span>src <span class="operator token">=</span> objectURL<span class="punctuation token">;</span></code></pre> + +<p>Конструктор <code>Request()</code> принимает точно такие же параметры, как и метод <code>fetch()</code>. Вы даже можете передать существующий объект запроса для создания его копии:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> anotherRequest <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Request</span><span class="punctuation token">(</span>myRequest<span class="punctuation token">,</span> myInit<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Довольно удобно, когда тела запроса и ответа используются единожды (прим.пер.: <em>"are one use only"</em>). Создание копии как показано позволяет вам использовать запрос/ответ повторно, при изменении опций <code>init</code>, при желании. Копия должна быть сделана до прочтения тела, а чтение тела в копии также пометит его прочитанным в исходном запросе.</p> + +<div class="note"> +<p><strong>Примечание</strong>: Также есть метод {{domxref("Request.clone","clone()")}}, создающий копии. Оба метода создания копии прекратят работу с ошибкой если тело оригинального запроса или ответа уже было прочитано, но чтение тела клонированного ответа или запроса не приведёт к маркировке оригинального.</p> +</div> + +<h2 id="Заголовки">Заголовки</h2> + +<p>Интерфейс {{domxref("Headers")}} позволяет вам создать ваш собственный объект заголовков через конструктор {{domxref("Headers.Headers","Headers()")}}. Объект заголовков - простая мультикарта имён-значений:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> content <span class="operator token">=</span> <span class="string token">'Hello World'</span><span class="punctuation token">;</span> +<span class="keyword token">const</span> myHeaders <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Headers</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +myHeaders<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'Content-Type'</span><span class="punctuation token">,</span> <span class="string token">'text/plain'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +myHeaders<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'Content-Length'</span><span class="punctuation token">,</span> content<span class="punctuation token">.</span>length<span class="punctuation token">.</span><span class="function token">toString</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +myHeaders<span class="punctuation token">.</span><span class="function token">append</span><span class="punctuation token">(</span><span class="string token">'X-Custom-Header'</span><span class="punctuation token">,</span> <span class="string token">'ProcessThisImmediately'</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>То же может быть достигнуто путём передачи массива массивов или литерального объекта конструктору:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> myHeaders <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Headers</span><span class="punctuation token">(</span><span class="punctuation token">{</span> + <span class="string token">'Content-Type'</span><span class="punctuation token">:</span> <span class="string token">'text/plain'</span><span class="punctuation token">,</span> + <span class="string token">'Content-Length'</span><span class="punctuation token">:</span> content<span class="punctuation token">.</span>length<span class="punctuation token">.</span><span class="function token">toString</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">,</span> + <span class="string token">'X-Custom-Header'</span><span class="punctuation token">:</span> <span class="string token">'ProcessThisImmediately'</span> +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Содержимое может быть запрошено и извлечено:</p> + +<pre class="brush: js">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")); // [ ]</pre> + +<p>Некоторые из этих операций могут быть использованы только в {{domxref("ServiceWorker_API","ServiceWorkers")}}, но они предоставляют более удобный API для манипуляции заголовками.</p> + +<p>Все методы Headers выбрасывают <code>TypeError</code>, если имя используемого заголовка не является валидным именем HTTP Header. Операции мутации выбросят <code>TypeError</code> если есть защита от мутации (смотрите ниже) (прим.пер.: <em>"if there is an immutable guard"</em>). В противном случае они прерываются молча. Например:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> myResponse <span class="operator token">=</span> Response<span class="punctuation token">.</span><span class="function token">error</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">try</span> <span class="punctuation token">{</span> + myResponse<span class="punctuation token">.</span>headers<span class="punctuation token">.</span><span class="function token">set</span><span class="punctuation token">(</span><span class="string token">'Origin'</span><span class="punctuation token">,</span> <span class="string token">'http://mybank.com'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">'Не могу притвориться банком!'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<p>Хорошим вариантом использования заголовков является проверка корректности типа контента перед его обработкой. Например:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">try</span> <span class="punctuation token">{</span> + <span class="keyword token">const</span> response <span class="operator token">=</span> <span class="keyword token">await</span> <span class="function token">fetch</span><span class="punctuation token">(</span>myRequest<span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">const</span> contentType <span class="operator token">=</span> response<span class="punctuation token">.</span>headers<span class="punctuation token">.</span><span class="function token">get</span><span class="punctuation token">(</span><span class="string token">'content-type'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span><span class="operator token">!</span>contentType <span class="operator token">||</span> <span class="operator token">!</span>contentType<span class="punctuation token">.</span><span class="function token">includes</span><span class="punctuation token">(</span><span class="string token">'application/json'</span><span class="punctuation token">)</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">throw</span> <span class="keyword token">new</span> <span class="class-name token">TypeError</span><span class="punctuation token">(</span><span class="string token">"Ой, мы не получили JSON!"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + <span class="keyword token">const</span> json <span class="operator token">=</span> <span class="keyword token">await</span> response<span class="punctuation token">.</span><span class="function token">json</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="comment token">/* Дальнейшая обработка JSON */</span> +<span class="punctuation token">}</span> <span class="keyword token">catch</span> <span class="punctuation token">(</span>error<span class="punctuation token">)</span> <span class="punctuation token">{</span> + console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>error<span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<h3 id="Защита">Защита</h3> + +<p>С тех пор как заголовки могут передаваться в запросе, приниматься в ответе и имеют различные ограничения в отношении того, какая информация может и должна быть изменена, заголовки имеют свойство guard. Это не распространяется на Web, но влияет на то, какие операции мутации доступны для объекта заголовков.</p> + +<p>Возможные значения:</p> + +<ul> + <li><code>none</code>: по умолчанию.</li> + <li><code>request</code>: защита объекта заголовков, полученного по запросу ({{domxref("Request.headers")}}).</li> + <li><code>request-no-cors</code>: защита объекта заголовков, полученного по запросу созданного с {{domxref("Request.mode")}} <code>no-cors</code>.</li> + <li><code>response</code>: защита Headers полученных от ответа ({{domxref("Response.headers")}}).</li> + <li><code>immutable</code>: в основном, используется в ServiceWorkers; делает объект заголовков read-only.</li> +</ul> + +<div class="note"> +<p><strong>Примечание</strong>: Вы не можете добавить или установить <code>request</code> защищаемые Headers’ заголовок <code>Content-Length</code>. Аналогично, вставка <code>Set-Cookie</code> в заголовок ответа недопустимо: ServiceWorkers не допускают установки cookies через синтезированные ответы.</p> +</div> + +<h2 id="Объекты_ответа">Объекты ответа</h2> + +<p>Как вы видели выше, экземпляр {{domxref("Response")}} будет возвращен когда <code>fetch()</code> промис будет исполнен.</p> + +<p>Свойства объекта-ответа которые чаще всего используются:</p> + +<ul> + <li>{{domxref("Response.status")}} — Целочисленное (по умолчанию 200) содержит код статуса ответа.</li> + <li>{{domxref("Response.statusText")}} — Строка (по умолчанию"OK"), которая соответствует HTTP коду статуса.</li> + <li>{{domxref("Response.ok")}} — как сказано ранее, это короткое свойство для упрощения проверки на то что статус ответа находится гдето между 200-299 включительно. Это свойство типа {{domxref("Boolean")}}.</li> +</ul> + +<p>Они так же могут быть созданы с помощью JavaScript, но реальная польза от этого есть только при использовании {{domxref("ServiceWorker_API", "сервисворкеров")}}, когда вы предоставляете собственный ответ на запрос с помощью метода {{domxref("FetchEvent.respondWith","respondWith()")}}:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> myBody <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">Blob</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + +<span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">'fetch'</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="parameter token">event</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// ServiceWorker перехватывает fetch</span> + event<span class="punctuation token">.</span><span class="function token">respondWith</span><span class="punctuation token">(</span> + <span class="keyword token">new</span> <span class="class-name token">Response</span><span class="punctuation token">(</span>myBody<span class="punctuation token">,</span> <span class="punctuation token">{</span> + headers<span class="punctuation token">:</span> <span class="punctuation token">{</span> <span class="string token">'Content-Type'</span><span class="punctuation token">:</span> <span class="string token">'text/plain'</span> <span class="punctuation token">}</span> + <span class="punctuation token">}</span><span class="punctuation token">)</span> + <span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Конструктор {{domxref("Response.Response","Response()")}} принимает два необязательных аргумента — тело для ответа и объект init (аналогичный тому, который принимает {{domxref("Request.Request","Request()")}})</p> + +<ul> +</ul> + +<div class="note"> +<p><strong>Примечание</strong>: Метод {{domxref("Response.error","error()")}} просто возвращает ответ об ошибке. Аналогично, {{domxref("Response.redirect","redirect()")}} возвращает ответ, приводящий к перенаправлению на указанный URL. Они также относятся только к Service Workers.</p> +</div> + +<h2 id="Тело">Тело</h2> + +<p>Запрос и ответ могут содержать данные тела. Тело является экземпляром любого из следующих типов:</p> + +<ul> + <li>{{domxref("ArrayBuffer")}}</li> + <li>{{domxref("ArrayBufferView")}} (Uint8Array и подобные)</li> + <li>{{domxref("Blob")}}/File</li> + <li>string</li> + <li>{{domxref("URLSearchParams")}}</li> + <li>{{domxref("FormData")}}</li> +</ul> + +<p>{{domxref("Body")}} примесь определяет следующие методы для извлечения тела (реализованны как для {{domxref("Request")}} так и для {{domxref("Response")}}). Все они возвращают promise, который в конечном итоге исполняется и выводит содержимое.</p> + +<ul> + <li>{{domxref("Body.arrayBuffer","arrayBuffer()")}}</li> + <li>{{domxref("Body.blob","blob()")}}</li> + <li>{{domxref("Body.json","json()")}}</li> + <li>{{domxref("Body.text","text()")}}</li> + <li>{{domxref("Body.formData","formData()")}}</li> +</ul> + +<p>Это делает использование нетекстовых данных более легким, чем при XMR.</p> + +<p>В запросе можно установить параметры для отправки тела запроса:</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">const</span> form <span class="operator token">=</span> <span class="keyword token">new</span> <span class="class-name token">FormData</span><span class="punctuation token">(</span>document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">'login-form'</span><span class="punctuation token">)</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="function token">fetch</span><span class="punctuation token">(</span><span class="string token">'/login'</span><span class="punctuation token">,</span> <span class="punctuation token">{</span> + method<span class="punctuation token">:</span> <span class="string token">'POST'</span><span class="punctuation token">,</span> + body<span class="punctuation token">:</span> form +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Параметры request и response (and by extension the <code>fetch()</code> function), по возможности возвращают корректные типы данных. Параметр request также автоматически установит <code>Content-Type</code> в заголовок, если он не был установлен из словаря.</p> + +<h2 id="Функция_обнаружения">Функция обнаружения</h2> + +<p>Поддержка Fetch API может быть обнаружена путем проверки наличия {{domxref("Headers")}}, {{domxref("Request")}}, {{domxref("Response")}} или {{domxref("GlobalFetch.fetch","fetch()")}} в области видимости {{domxref("Window")}} или {{domxref("Worker")}}. Для примера:</p> + +<pre class="brush: js">if (self.fetch) { + // запустить мой fetch запрос здесь +} else { + // Сделать что-то с XMLHttpRequest? +}</pre> + +<h2 id="Полифилл">Полифилл</h2> + +<p>Для того, чтобы использовать Fetch в неподдерживаемых браузерах, существует <a href="https://github.com/github/fetch">Fetch Polyfill</a> , который воссоздает функциональность для не поддерживающих браузеров.</p> + +<h2 id="Спецификации">Спецификации</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Спецификации</th> + <th scope="col">Статус</th> + <th scope="col">Комментарий</th> + </tr> + <tr> + <td>{{SpecName('Fetch')}}</td> + <td>{{Spec2('Fetch')}}</td> + <td>Первоначальное описание</td> + </tr> + </tbody> +</table> + +<h2 id="Совместимость_браузера">Совместимость браузера</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Базовая поддержка</td> + <td>{{CompatChrome(42)}}</td> + <td>14</td> + <td>{{CompatGeckoDesktop(39)}}<br> + {{CompatGeckoDesktop(34)}}<sup>[1]</sup><br> + {{CompatGeckoDesktop(52)}}<sup>[2]</sup></td> + <td>{{CompatNo}}</td> + <td>29<br> + 28<sup>[1]</sup></td> + <td>10.1</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android Webview</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + <th>Chrome for Android</th> + </tr> + <tr> + <td>Базовая поддержка</td> + <td>{{CompatChrome(42)}}</td> + <td>{{CompatChrome(42)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatUnknown}}</td> + <td>10.1</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Этот API is implemented behind a preference.</p> + +<p>[2] До Firefox 52, <code>get()</code> возращал только первое значение в указанном заголовке, а <code>getAll()</code> возращал все значения. Начиная с 52, <code>get()</code> теперь возращает все значения и <code>getAll()</code> был удален.</p> + +<h2 id="См._также">См. также</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/ServiceWorker_API">ServiceWorker API</a></li> + <li><a href="/en-US/docs/Web/HTTP/Access_control_CORS">HTTP access control (CORS)</a></li> + <li><a href="/en-US/docs/Web/HTTP">HTTP</a></li> + <li><a href="https://github.com/github/fetch">Fetch polyfill</a></li> + <li><a href="https://github.com/mdn/fetch-examples/">Fetch examples on Github</a></li> +</ul> |