- Операторы
- Управляющие инструкции
- JS Объекты
- браузер BOM
- HTML DOM
- События
- HTML Объекты
- Промисы, async/await
- Сетевые запросы
- XMLHttpRequest
- Объекты URL
- Объект formData
- Fetch API
- Fetch API 2
- Бинарные данные и файлы
- Разное
Fetch API
Fetch API – это простой и современный интерфейс, который позволяет выполнять сетевые запросы и обрабатывать ответы от сервера. Т.е. решает те же задачи, что XMLHttpRequest (XHR).Самым большим отличием Fetch
от XMLHttpRequest
является то, что первый использует промисы, которые значительно упрощают работу с запросами и ответами. Код на Fetch
получается более простым и чистым.
Начиная с ES7, вы можете использовать async-await и полностью избавиться от promises.
метод fetch()
Fetch API предоставляет глобальный метод fetch():
let promise = fetch(url, [options]);
url
- URL для отправки запроса.options
- Дополнительные параметры, содержащие пользовательские настройки:
- method:
Метод запроса (GET, POST, PUT, DELETE, HEAD);.
- headers:
HTTP-заголовки, содержащиеся в объекте, например:
let response = fetch(protectedUrl, { headers: { Authentication: 'secret' } });
Есть список запрещённых HTTP-заголовков, которые мы не можем установить:
Accept-Charset
,Accept-Encoding
,Access-Control-Request-Headers
,Access-Control-Request-Method
,Connection
,Content-Length
,Cookie
,Cookie2
,Date
,DNT
,Expect
,Host
,Keep-Alive
,Origin
,Referer
,TE
,Trailer
,Transfer-Encoding
,Upgrade
,Via
,Proxy-*
,Sec-*
.Эти заголовки обеспечивают достоверность данных и корректную работу протокола HTTP, поэтому они контролируются исключительно браузером.
- body:
Тело запроса (используется при method: POST / PUT):
- строка (например, в формате JSON),
- объект
FormData
для отправки данных какform/multipart
, Blob
/BufferSource
для отправки бинарных данных,- URLSearchParams для отправки данных в кодировке
x-www-form-urlencoded
, используется редко.
Чаще всего используется JSON.
Например, этот код отправляет объект
user
как JSON:(async () => { let user = { name: 'John', surname: 'Smith' }; let response = await fetch('xhr/f1.php', { method: 'POST', headers: { 'Content-Type': 'application/json;charset=utf-8' }, body: JSON.stringify(user) }); let result = await response.text(); alert(result); })();
Заметим, что так как тело запроса
body
– строка, то заголовокContent-Type
по умолчанию будетtext/plain;charset=UTF-8
.
Но, так как мы посылаем JSON, то используем параметрheaders
для отправки вместо этогоapplication/json
, правильныйContent-Type
для JSON. - mode:
Защита от нечаянной отправки запроса на другой источник:
"cors"
– стоит по умолчанию, позволяет делать такие запросы так, как описано в Fetch: запросы на другие сайты,"same-origin"
– запросы на другой источник запрещены,"no-cors"
– разрешены только простые запросы на другой источник.
Эта опция может пригодиться, если URL-адрес для
fetch
приходит от третьей стороны, и нам нужен своего рода «глобальный выключатель» для запросов на другие источники. - credentials:
Опция
credentials
указывает, должен лиfetch
отправлять куки и авторизационные заголовки HTTP вместе с запросом."same-origin"
– стоит по умолчанию, не отправлять для запросов на другой источник,"include"
– отправлять всегда, но при этом необходим заголовокAccess-Control-Allow-Credentials
в ответе от сервера, чтобы JavaScript получил доступ к ответу сервера Fetch: запросы на другие сайты,"omit"
– не отправлять ни при каких обстоятельствах, даже для запросов, сделанных в пределах текущего источника.
- cache:
По умолчанию
fetch
делает запросы, используя стандартное HTTP-кеширование. То есть, учитывается заголовкиExpires
,Cache-Control
, отправляетсяIf-Modified-Since
и так далее. Так же, как и обычные HTTP-запросы.Настройка
cache
позволяет игнорировать HTTP-кеш или же настроить его использование:"default"
–fetch
будет использовать стандартные правила и заголовки HTTP кеширования,"no-store"
– полностью игнорировать HTTP-кеш, этот режим становится режимом по умолчанию, если присутствуют такие заголовки какIf-Modified-Since
,If-None-Match
,If-Unmodified-Since
,If-Match
, илиIf-Range
,"reload"
– не брать результат из HTTP-кеша (даже при его присутствии), но сохранить ответ в кеше (если это дозволено заголовками ответа);"no-cache"
– в случае, если существует кешированный ответ – создать условный запрос, в противном же случае – обычный запрос. Сохранить ответ в HTTP-кеше,"force-cache"
– использовать ответ из HTTP-кеша, даже если он устаревший. Если же ответ в HTTP-кеше отсутствует, сделать обычный HTTP-запрос, действовать как обычно,"only-if-cached"
– использовать ответ из HTTP-кеша, даже если он устаревший. Если же ответ в HTTP-кеше отсутствует, то выдаётся ошибка. Это работает, только когдаmode
установлен в"same-origin"
.
- redirect
Обычно
fetch
прозрачно следует HTTP-редиректам, таким как 301, 302 и так далее.Это можно поменять при помощи опции
redirect
:"follow"
– стоит по умолчанию, следовать HTTP-редиректам,"error"
– ошибка в случае HTTP-редиректа,"manual"
– не следовать HTTP-редиректу, но установить адрес редиректа вresponse.url
, аresponse.redirected
будет иметь значениеtrue
, чтобы мы могли сделать перенаправление на новый адрес вручную.
- referrer:
Данные опции определяют, как
fetch
устанавливает HTTP-заголовокReferer
.Обычно этот заголовок ставится автоматически и содержит URL-адрес страницы, с которой пришёл запрос. В большинстве случаев он совсем неважен, в некоторых случаях, с целью большей безопасности, имеет смысл убрать или укоротить его.
Опция
referrer
позволяет установить любойReferer
в пределах текущего источника или же убрать его.Чтобы не отправлять
Referer
, нужно указать значением пустую строку:fetch('/page', { referrer: "" // не ставить заголовок Referer });
Для того, чтобы установить другой URL-адрес (должен быть с текущего источника):
fetch('/page', { // предположим, что мы находимся на странице https://site.info // мы можем установить любое значение Referer при условии, что оно принадлежит текущему источнику referrer: "https://site.info/anotherpage" });
- referrerPolicy:
Опция
referrerPolicy
устанавливает общие правила дляReferer
.Выделяется 3 типа запросов:
- Запрос на тот же источник.
- Запрос на другой источник.
- Запрос с HTTPS to HTTP (с безопасного протокола на небезопасный).
В отличие от настройки
referrer
, которая позволяет задать точное значениеReferer
, настройкаreferrerPolicy
сообщает браузеру общие правила, что делать для каждого типа запроса.Возможные значения описаны в спецификации Referrer Policy:
"no-referrer-when-downgrade"
– это значение по умолчанию:Referer
отправляется всегда, если только мы не отправим запрос из HTTPS в HTTP (из более безопасного протокола в менее безопасный)."no-referrer"
– никогда не отправлятьReferer
."origin"
– отправлять вReferer
только текущий источник, а не полный URL-адрес страницы, например, посылать толькоhttp://site.com
вместоhttp://site.com/path
."origin-when-cross-origin"
– отправлять полный Referer для запросов в пределах текущего источника, но для запросов на другой источник отправлять только сам источник (как выше)."same-origin"
– отправлять полный Referer для запросов в пределах текущего источника, а для запросов на другой источник не отправлять его вообще."strict-origin"
– отправлять только значение источника, не отправлять Referer для HTTPS→HTTP запросов."strict-origin-when-cross-origin"
– для запросов в пределах текущего источника отправлять полный Referer, для запросов на другой источник отправлять только значение источника, в случае HTTPS→HTTP запросов не отправлять ничего."unsafe-url"
– всегда отправлять полный URL-адрес вReferer
, даже при запросахHTTPS→HTTP
.
Допустим, у нас есть админка со структурой URL, которая не должна стать известной снаружи сайта.
Если мы отправляем запрос
fetch
, то по умолчанию он всегда отправляет заголовокReferer
с полным URL-адресом нашей админки (исключение – это когда мы делаем запрос от HTTPS в HTTP, в таком случаеReferer
не будет отправляться).Например,
Referer: https://site.info/admin/secret/paths
.Если мы хотим, чтобы другие сайты получали только источник, но не URL-путь, это сделает такая настройка:
fetch('https://another.com/page', { // ... referrerPolicy: "origin-when-cross-origin" // Referer: https://site.info });
Мы можем поставить её во все вызовы
fetch
, возможно, интегрировать в JavaScript-библиотеку нашего проекта, которая делает все запросы и внутри используетfetch
.Единственным отличием в поведении будет то, что для всех запросов на другой источник
fetch
будет посылать только источник в заголовкеReferer
(например,https://site.info
, без пути). А для запросов на наш источник мы продолжим получать полныйReferer
(это может быть полезно для отладки).Политика установки Referer, описанная в спецификации Referrer Policy, существует не только для
fetch
, она более глобальная.В частности, можно поставить политику по умолчанию для всей страницы, используя HTTP-заголовок
Referrer-Policy
, или на уровне ссылки<a rel="noreferrer">
. - integrity:
Опция
integrity
позволяет проверить, соответствует ли ответ известной заранее контрольной сумме.Как описано в спецификации, поддерживаемыми хеш-функциями являются SHA-256, SHA-384 и SHA-512. В зависимости от браузера, могут быть и другие.
Например, мы скачиваем файл, и мы точно знаем, что его контрольная сумма по алгоритму SHA-256 равна «abcdef» (разумеется, настоящая контрольная сумма будет длиннее).
Мы можем добавить это в настройку
integrity
вот так:fetch('http://site.com/file', { integrity: 'sha256-abcdef' });
Затем
fetch
самостоятельно вычислит SHA-256 и сравнит его с нашей строкой. В случае несоответствия будет ошибка. - keepalive:
Опция
keepalive
указывает на то, что запрос может «пережить» страницу, которая его отправила.Например, мы собираем статистические данные о том, как посетитель ведёт себя на нашей странице (на что он кликает, части страницы, которые он просматривает), для анализа и улучшения интерфейса.
Когда посетитель покидает нашу страницу – мы хотим сохранить собранные данные на нашем сервере.
Для этого мы можем использовать событие
window.onunload
:window.onunload = function() { fetch('/analytics', { method: 'POST', body: "statistics", keepalive: true }); };
Обычно, когда документ выгружается, все связанные с ним сетевые запросы прерываются. Но настройка
keepalive
указывает браузеру выполнять запрос в фоновом режиме даже после того, как пользователь покидает страницу. Поэтому эта опция обязательна, чтобы такой запрос удался.У неё есть ряд ограничений:
- Мы не можем посылать мегабайты: лимит тела для запроса с
keepalive
– 64кб.- Если мы собираем больше данных, можем отправлять их регулярно, «пакетами», тогда на момент последнего запроса в
onunload
их останется немного. - Этот лимит распространяется на все запросы с
keepalive
. То есть, мы не можем его обойти, послав 100 запросов одновременно – каждый по 64Кбайт.
- Если мы собираем больше данных, можем отправлять их регулярно, «пакетами», тогда на момент последнего запроса в
- Мы не сможем обработать ответ от сервера, если запрос сделан при
onunload
: в тот момент документ уже выгружен, его функции не сработают.- Обычно сервер посылает пустой ответ на такие запросы, так что это не является проблемой.
- Мы не можем посылать мегабайты: лимит тела для запроса с
- signal:
Экземпляр объекта
AbortSignal
; позволяет коммуницировать сfetch
запросом и, если нужно, отменять его с помощьюAbortController
. См. Fetch: прерывание запроса
Возвращаемое значение
Метод Fetch возвращает Promise, содержащий объект Response
(ответ на запрос).
С помощью свойств объекта Response можно получить из полученного ответа различную информацию. Объект Response имеет следующие свойства:
body: содержимое ответа в виде объекта ReadableStream
bodyUsed: хранит булевое значение, которое указывает, было ли содержимое ответа уже использовано.
headers: набор заголовков ответа в виде объекта Headers, для которого можно использовать методы:
- Headers.entries() - Возвращает итератор, позволяющий пройтись по всем парам ключ/значение, содержащимся в этом объекте.
- Headers.forEach() - Выполняет предоставленную функцию один раз для каждой пары ключ/значение в этом объекте Headers.
- Headers.get() - Возвращает последовательность String всех значений заголовка в объекте Headers с заданным именем.
- Headers.has() - Возвращает логическое значение, указывающее, содержит ли объект Headers определенный заголовок.
- Headers.keys() -Возвращает итератор, позволяющий просмотреть все ключи пар ключ/значение, содержащихся в этом объекте.
- Headers.values() - Возвращает итератор, позволяющий просмотреть все значения пар ключ/значение, содержащихся в этом объекте.
Заголовки ответа хранятся в похожем на
Map
объектеresponse.headers
.Это не совсем
Map
, но мы можем использовать такие же методы, как сMap
, чтобы получить заголовок по его имени или перебрать заголовки в цикле:(async () => { let response = await fetch('xhr/f1.php'); // получить один заголовок var s = response.headers.get('Content-Type') + '\n'; // перебрать все заголовки for (let [key, value] of response.headers) s += `\n${key} = ${value}`; alert(s);})();
ok: хранит булевое значение, которое указывает, завершился ли запрос успешно (то есть если статусной код ответа находится в диапазоне 200-299)
redirected: хранит булевое значение, которое указывает, является ли ответ результатом переадресации
status: хранит статусный код ответа
statusText: хранит сообщение статуса, которое соответствует статусному коду
type: хранит тип ответа
url: хранит адрес URL. Если в процессе запроса происходит ряд переадресаций, то хранит конечный адрес URL после всех переадресаций
promise
выполняется с объектом встроенного класса Response
в качестве результата, как только сервер пришлёт заголовки ответа.
На этом этапе мы можем проверить статус HTTP-запроса и определить, выполнился ли он успешно, а также посмотреть заголовки, но пока без тела ответа.
Промис завершается с ошибкой, если fetch
не смог выполнить HTTP-запрос, например при ошибке сети или если нет такого сайта. HTTP-статусы 404 и 500 не являются ошибкой.
Мы можем увидеть HTTP-статус в свойствах ответа:
status
– код статуса HTTP-запроса, например 200.ok
– логическое значение: будетtrue
, если код HTTP-статуса в диапазоне 200-299.
Например:
let response = await fetch(url); if (response.ok) { // если HTTP-статус в диапазоне 200-299 // получаем тело ответа (см. про этот метод ниже) let json = await response.json(); } else { alert("Ошибка HTTP: " + response.status); }
Для получения тела ответа нам нужно использовать дополнительный вызов метода.
Response
предоставляет несколько методов, основанных на промисах, для доступа к телу ответа в различных форматах:
- response.text() – читает ответ и возвращает как обычный текст,
- response.json() – декодирует ответ в формате JSON,
- response.formData() – возвращает ответ как объект FormData,
- response.blob() – возвращает объект как Blob (бинарные данные с типом),
- response.arrayBuffer() – возвращает ответ как ArrayBuffer (низкоуровневое представление бинарных данных),
- помимо этого,
response.body
– это объект ReadableStream, с помощью которого можно считывать тело запроса по частям.
Например, получим JSON-объект с последними коммитами из репозитория на GitHub:
(async () => { let url = 'xhr/periodic_table.json'; let response = await fetch(url); let commits = await response.json(); // читаем ответ в формате JSON alert(commits[0].elementName); })()
То же самое без await, с использованием промисов:
fetch('xhr/periodic_table.json') .then(response => response.json()) .then(commits => alert(commits[0].elementName));
Для получения ответа в виде текста используем await response.text()
вместо .json()
:
(async () => { let response = await fetch('xhr/periodic_table.json'); let text = await response.text(); // прочитать тело ответа как текст alert(text.slice(0, 80) + '...'); })()
В качестве примера работы с бинарными данными, давайте запросим и выведем на экран логотип спецификации «fetch»:
(async () => { let response = await fetch('image/logo-fetch.svg'); let blob = await response.blob(); // скачиваем как Blob-объект // создаём <img> let img = document.createElement('img'); img.style = 'position:fixed;top:30px;right:20px;width:192px'; document.body.append(img); // выводим на экран img.src = URL.createObjectURL(blob); setTimeout(() => { // прячем через три секунды img.remove(); URL.revokeObjectURL(img.src); }, 3000); })();
Мы можем выбрать только один метод чтения ответа.
Если мы уже получили ответ с response.text()
, тогда response.json()
не сработает, так как данные уже были обработаны.
let text = await response.text(); // тело ответа обработано let parsed = await response.json(); // ошибка (данные уже были обработаны)
Комментарии
Типичный запрос с помощью fetch
состоит из двух операторов await
:
let response = await fetch(url, options); // завершается с заголовками ответа let result = await response.json(); // читать тело ответа в формате JSON
Или, без await
:
fetch(url, options) .then(response => response.json()) .then(result => /* обрабатываем результат */)
Примеры
Отправка изображения
Мы можем отправить бинарные данные при помощи fetch
, используя объекты Blob
или BufferSource
.
В этом примере есть элемент <canvas>
, на котором мы можем рисовать движением мыши. При нажатии на кнопку «Отправить» изображение отправляется на сервер:
<canvas id="canvasElem" width="192" height="192" style="border:1px solid"></canvas> <input type="button" value="Нарисуйте «мышкой» и Отправить" onclick="submit()"> <script> canvasElem.onmousemove = function(e) { let ctx = canvasElem.getContext('2d'); ctx.lineTo(e.clientX, e.clientY); ctx.stroke(); }; async function submit() { let blob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png')); let response = await fetch('xhr/f2.php', { method: 'POST', body: blob }); // сервер ответит подтверждением и размером изображения let result = await response.text(); alert(result); } </script>
Пример использования fetch() для получения JSON
Получить информацию о пользователях в формате JSON.
HTML-код:<input type="text" id="user-id" value="1"> <button type="button" id="get-user">Получить user по id</button> <button type="button" id="get-users">Вывести всех</button> <div id="result"></div> <script> // функция для получения данных с сервера и вывода их на страницу const getUsers = async (id = -1) => { try { // использование метода fetch() для отправки асинхронного запроса на сервер let response = await fetch(`xhr/f3.php?id=${id}`); if (response.ok) { // получаем ответ в формате JSON и сохраняем его в data let data = await response.json(); // выполняем рендеринг полученных данных в элемент #result const count = data['count']; let html = `<div style="margin-bottom: 10px;">Найдено: ${count}</div>`; for (const key in data['data']) { const user = data['data'][key]; html += `<div style="background-color: #fafafa; display: flex; border-radius: 5px; overflow: hidden; margin-bottom: 10px;"> <img src="${user['avatar_url']}" alt="${user['name']}"> <ul> <li>Имя: ${user['name']}</li> <li>Email: ${user['email']}</li> <li>Страна: ${user['location']}</li> </ul> </div>`; } // выведем данные в #result document.querySelector('#result').innerHTML = html; } } catch (error) { сonsole.log(error); } } // при клике на #get-user document.querySelector('#get-user').onclick = () => { const id = parseInt(document.querySelector('#user-id').value); // вызовем функцию getUser и передадим ей id пользователя который нужно получить getUsers(id); } // при клике на #get-users вызовем функцию getUser document.querySelector('#get-users').onclick = () => { getUsers(); } </script>
Далее для сравнения показаны примеры от XMLHttpRequest
Для прсмотра необходимо "кликнуть мышкой" на HTML
или Результат
Пример 1
<script> async function loadXMLDoc() { var myDiv = document.getElementById("myDiv"); let response = await fetch("xhr/fetch_info.txt"); if (response.ok) { // если HTTP-статус в диапазоне 200-299 myDiv.innerHTML = await response.text(); } else { myDiv.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <h2>Использование fetch</h2> <div id="myDiv"></div> <button type="button" onclick="loadXMLDoc()"> Попробуйте </button>
Пример 2
<script> async function loadXMLDoc(file) { var s='', myDiv = document.getElementById("myDiv"); let response = await fetch(file); if (response.ok) { // если HTTP-статус в диапазоне 200-299 // перебрать все заголовки for (let [key, value] of response.headers) s += `n${key} = ${value}<br>`; myDiv.innerHTML = s; } else { myDiv.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <div id="myDiv"></div> <button type="button" onclick="loadXMLDoc('xhr/fetch_info.txt')"> Получить заголовочную информацию </button>
Пример 3
<script> async function loadXMLDoc(file) { var myDiv = document.getElementById("myDiv"); let response = await fetch(file); if (response.ok) { // если HTTP-статус в диапазоне 200-299 myDiv.innerHTML = response.headers.get('Content-Type'); } else { myDiv.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <div id="myDiv"></div> <button type="button" onclick="loadXMLDoc('xhr/fetch_info.txt')"> Получить информацию по заголовку "Content-Type" </button>
Пример 4
<script> async function showCustomer(str) { var myDiv = document.getElementById("myDiv"); let response = await fetch("xhr/ex4.php?q="+str); if (response.ok) { myDiv.innerHTML = await response.text(); } else { myDiv.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <select onchange="showCustomer(this.value)"> <option value="">Изменить клиента:</option> <option value="PETROVI">Иван Петров</option> <option value="SIDOROVV">Василий Сидоров</option> <option value="BYKOVA">Андрей Быков</option> </select><br><br> <div id="myDiv"> Информация о клиенте будет показана здесь...</div>
Пример 5
<script> async function loadXMLDoc(url) { var s, x, txt, xml, myDiv = document.getElementById("myDiv"); let response = await fetch(url); if (response.ok) { s = await response.text(); xml = new window.DOMParser().parseFromString(s, "text/xml"); txt="<table border='1'><tr>" + "<th>Заголовок</th>" + "<th>Артист</th>"+ "</tr>"; x = xml.documentElement.getElementsByTagName("CD"); for (i=0;i<x.length;i++) { txt=txt + "<tr>"; xx=x[i].getElementsByTagName("TITLE"); try { txt=txt + "<td>" + xx[0].firstChild.nodeValue + "</td>"; } catch (er) { txt=txt + "<td> </td>"; } xx=x[i].getElementsByTagName("ARTIST"); try { txt=txt + "<td>" + xx[0].firstChild.nodeValue + "</td>"; } catch (er) { txt=txt + "<td> </td>"; } txt=txt + "</tr>"; } txt=txt + "</table>"; myDiv.innerHTML=txt; } else { myDiv.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <div id="myDiv"><h3> Получение содержимого XML файла </h3> <button onclick="loadXMLDoc('xhr/cd_catalog.xml')"> Получить информацию о CD дисках </button> </div>
Пример 6
<script> async function showHint(str) { var p1 = document.getElementById("p1"); let response = await fetch("xhr/ex6.php?q="+encodeURIComponent(str)); if (response.ok) { p1.innerHTML = await response.text(); } else { p1.innerHTML = "Ошибка HTTP: " + response.status; } } </script> <h3>Начните печатать русскими буквами имя в поле ввода ниже:</h3> Имя: <input type="text" id="txt1" onkeyup="showHint(this.value)" /> <p>Предложения: <span id="p1"></span></p>
Пример 7
<style> li b {display: inline-block; width:32px;} li span {display: inline-block; width:96px;} </style> <button onclick="loadTable()"> Загрузить periodic_table.json! </button> <p id="p1"></p> <ul id="list"></ul> <script> async function loadTable() { let response = await fetch("xhr/periodic_table.json"); if (!response.ok) { p1.innerHTML = "Ошибка HTTP: " + response.status; return;} var table = await response.json(); table.forEach(function(el) { var li = list.appendChild(document.createElement('li')); li.innerHTML = el.elementNumb + ': <b>' + el.elementChar + '</b> <span>' + el.elementName + '</span> ' + decodeURIComponent(el.url); }); } </script>
Пример 8
<form name="person"> <table> <tr><td style="text-align:right"> Имя: </td><td><input name="name" value="Никита"></td></tr> <tr><td style="text-align:right"> Фамилия: </td><td><input name="surname" value="Рябков"></td></tr> </table> </form> <button onclick="sentForma()"> Отправить на сервер </button> <div id="output"></div> <script> // создать объект для формы var formData = new FormData(document.forms.person); // добавить к пересылке ещё пару ключ - значение formData.append("Age", "33"); formData.append("Profession", "Програмист"); async function sentForma () { let response = await fetch('xhr/ex8.php', { method: 'POST', body: formData }); document.getElementById("output").innerHTML = await response.text(); } </script>
Пример 9
// POST-запросы var user = { name: "Tom", age: 23 }; (async () => { let response = await fetch('xhr/postdata.php', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: "name=" + user.name + "&age="+user.age }); document.getElementById("output").innerHTML = "На Ваш запрос отвечаю:<br>" + await response.text(); setTimeout(() => { // прячем через 5 секунды document.getElementById("output").innerHTML = ""; }, 5000); })();
<?php $name = "Не известно"; $age = "Не известно"; if(isset($_POST['name'])) $name = $_POST['name']; if (isset($_POST['age'])) $age = $_POST['age']; echo "Ваше имя: $name <br> Ваш возраст: $age"; ?>
Пример 10. Определить форму в html и использовать ее для отправки
<form name="user" action="xhr/postdata.php"> <input type="text" name="name" placeholder="Введите имя" /><br/> <input type="text" name="age" placeholder="Введите возраст" /><br/> <input type="submit" name="submit" value="Отправить" /> </form> <p id="output"></p> <script> // получаем объект формы var form = document.forms.user; // прикрепляем обработчик кнопки form.submit.addEventListener("click", sendRequest); // обработчик нажатия async function sendRequest(event) { event.preventDefault(); var formData = new FormData(form); let response = await fetch(form.action, { method: 'POST', body: formData }); if (response.ok) document.getElementById("output").innerHTML = await response.text(); }; </script> </body> </html>