JavaScript - Синхронный AJAX запрос (XMLHttpRequest)
Урок, в котором на простых примерах разберем, как работать с технологией AJAX, а именно познакомимся с тем как с помощью объекта XMLHttpRequest (сокращённо XHR) создавать синхронные HTTP-запросы к серверу и получать от него ответы.
Основы AJAX
Знакомство с технологией AJAX начнём с рассмотрения примера (для начинающих), который будет запрашивать информацию с сервера посредством синхронного запроса.
Синхронный запрос в отличие от асинхронного, после его отправки и до получения ответа, замораживает веб-страницу, т.е. делает её недоступной для пользователя. Синхронные запросы на сайтах используются довольно редко, но изучать технологию AJAX начинающим лучше именно с них.
Перед тем как перейти к созданию примера, рассмотрим основные этапы, сопровождающие разработку фрагмента страницы, работающей в соответствии с технологией AJAX. При этом все действия в основном осуществляются в коде JavaScript после наступления какого-либо события на странице (пользователь нажал кнопку и т.п.) и состоят из следующих этапов:
- Получение некоторой информации (данных) со страницы или формы (при необходимости)
- Отправление запрос на веб-сервер
- Получение ответа с веб-сервера
- Отображение результатов на странице, если ответ был успешен.

Пример 1. Выполнение синхронного AJAX запроса
Рассмотрим пример выполнения синхронного AJAX запроса к серверу с помощью метода XMLHttpRequest. В данном примере запросим данные, находящиеся в файле data.txt
на сервере и отобразим их на странице в элементе span
.
Пример будет состоять из файлов index.html
, script.js
и data.txt
, которые для простоты можно расположить на сервере в одном каталоге.
Начнём разработку с создания HTML-страницы, к которой подключим файл script.js
. Этот файл, а точнее его содержимое будет выполнять всю основную работу. Но перед тем как перейти к его разработке, создадим на станице элементы div
и span
. Элемент div
будет играть роль кнопки, при нажатии на которую будет выполняться AJAX запрос. А элемент span
будет играть роль контейнера, который будет содержать ответ, пришедший с сервера.
Кроме этого добавим на страницу ещё стили CSS, чтобы немного её оформить. В итоге у нас должен получиться следующий HTML код:
<html lang="ru"> <head> <meta charset="utf-8"> <title>JavaScript AJAX</title> <style> #myDiv { height: 30px; width: 100px; background-color: lightgreen; } span { font-weight: bold; color: red; } </style> </head> <body> <div id="myDiv"></div> <p>Ответ (AJAX): <span id="answer"></span></p> <script src="script.js"></script> </body> </html>
После этого откроем файл data.txt
и введём в него текст "Привет, мир!". Сохраним и закроем файл.
И наконец, перейдём к созданию файла script.js
. Содержимое этого файла будет выполнять все основные действия, т.е. отправлять ajax запрос на сервер, принимать от сервера ответ и обновлять содержимое страницы (помещать ответ в элемент span
).
Рассмотрим создание данного файла поэтапно:
-
Получим элемент на событие
click
которого необходимо подписаться.var myDiv = document.getElementById("myDiv");
-
Подпишемся на событие
click
элемента с помощью методаaddEventListener
.myDiv.addEventListener("click", function(){ // дейcтвия которые будут выполняться, при клике на элемент div, имеющий id="myDiv" });
-
Создадим переменную
request
, которая будет содержать экземпляр объектаXMLHttpRequest
.var request = new XMLHttpRequest();
Примечание: В коде JavaScript создание синхронных, а также асинхронных HTTP-запросов осуществляется с помощью объектаXMLHttpRequest
. Т.е. данный объект предназначен для конфигурирования запроса, отправление его серверу и получения от него ответа. -
Настроим HTTP-запрос к серверу с помощью метода open. Данный метод имеет 3 основных параметра. 1 параметр отвечает за метод, с помощью которого мы отправляем данные на сервер. Различают два основных метода: GET и POST. Метод GET передаёт данные в составе URL после знака
?
(для отделения данных используется амперсанд&
).Метод GET Метод POST передаёт данные в теле HTTP-запроса.
Метод POST 2 параметр отвечает за адрес (URL), по которому посылается запрос. А 3 параметр определяет тип запроса: синхронный (
false
) или асинхронный (true
).// настраиваем запрос: //GET - метод отправки запроса //data.txt - URL, содержащий данные //false - метод отправки запроса request.open('GET','data.txt',false);
Примечание: Из-за того что файл data.txt расположен в том же каталоге что и документ, путь к нему можно не указывать.Внимание: По правилу ограничения домена (Same Origin Policy), Вы не можете запрашивать данные источников, у которых домен, протокол и порт не соответствуют Вашей страницы. -
Отправляем ajax запрос на сервер.
request.send();
После отправки синхронного запроса на сервер, наша страница замораживается (т.е. не отвечает на запросы пользователя) и ждёт ответа от сервера. Как только ответ приходит, он становится доступным в виде следующих свойств объекта
XMLHttpRequest
:status
(статус запроса). Если значение свойства равно 200, то запрос выполнен успешно. Если вstatus
хранится другое число, значит, запрос завершился с ошибкой (например, 404, 500 и т.д.)responseText
– содержит текст ответа, который пришёл от сервера. Т.е. данное свойство всегда содержит то, что нам нужно, если статус ответа был 200.
Посмотреть на этот объект можно, например, в консоли, для этого после отправки ajax запроса на сервер достаточно поместить в код следующую строчку:
console.log(request);
Просмотр объекта XMLHttpRequest в консоли браузера -
Получаем результат и отображаем его на странице.
if (request.status==200) { document.getElementById("answer").innerHTML = request.responseText; }
<html lang="ru"> <head> <meta charset="utf-8"> <title>JavaScript AJAX</title> <style> #myDiv { height: 30px; width: 100px; background-color: lightgreen; } span { font-weight: bold; color: red; } </style> </head> <body> <p>Нажмите на светло-зелёный блок и получите ответ с сервера "Пример, мир!".</p> <div id="myDiv"></div> <p>Ответ (AJAX): <span id="answer"></span></p> <script src="script.js"></script> </body> </html>
// получить элемент, имеющий id="myDiv" var myDiv = document.getElementById("myDiv"); // подпишемся на событие click этого элемента myDiv.addEventListener("click", function() { // создадим объект XMLHttpRequest var request = new XMLHttpRequest(); //настраиваем запрос: GET - метод, data.txt - URL-адрес по которому будет посылаться запрос, false - синхронный запрос request.open('GET','data.txt',false); // отправляем данные на сервер с помощью метода send request.send(); // если статус ответа 200 (OK) то if (request.status==200) { // выведем в элемент, имеющий id="answer", ответ сервера document.getElementById("answer").innerHTML = request.responseText; } })
Привет, мир!
Пример 2. Обработка синхронного AJAX запроса на сервере с помощью PHP
Пример, который будет по технологии AJAX передавать серверу запрос, содержащий параметр и отображать ответ на странице.
В данном примере страница будет состоять из 3 кнопок. Первая кнопка будет иметь текст 1, вторая кнопка текст 2 и третья кнопка текст 3. При нажатии на любую из кнопок будет выполняться синхронный запрос на сервер. В качестве метода передачи запроса будем использовать GET. А адрес, по которому будем посылать запрос и параметры ajax.php
. Получать данные отправленные клиентом на сервере будем с помощью GET-переменной HTTP ($_GET). После этого полученные данные будем обрабатывать на сервере, и возвращать клиенту ответ (строку).
<html lang="ru"> <head> <meta charset="utf-8"> <title>JavaScript AJAX</title> <style> span { font-weight: bold; color: red; } </style> </head> <body> <p>Нажмите на одну из кнопок и получите ответ с сервера посредством технологии AJAX.</p> <div style="text-center;"> <button>1</button> <button>2</button> <button>3</button> </div> <p>Ответ (AJAX): <span id="answer"></span></p> <script src="script.js"></script> </body> </html>
// получить все элементы button на странице var buttons = document.getElementsByTagName("button"); // подпишемся на событие click все элементов button for (var i=0; i<buttons.length; i++) { buttons[i].addEventListener("click",function(){ // создадим объект XMLHttpRequest var request = new XMLHttpRequest(); //настраиваем запрос: GET - метод, ajax.php - URL-адрес по которому будет посылаться запрос, false - синхронный запрос //передавать параметр будем в составе URL request.open('GET','ajax.php?button='+this.textContent+'',false); // отправляем данные на сервер с помощью метода send request.send(); // если статус ответа 200 (OK) то if (request.status==200) { // выведем в элемент, имеющий id="answer", ответ сервера document.getElementById("answer").innerHTML = request.responseText; } } })
<?php // массив fructs $fructs = array("Яблоки","Виноград","Апельсин"); // если в ассоциативном массиве $_GET существует ключ button if (isset($_GET['button'])) { // присвоим переменной $button значение из ассоциативного массива GET соответсвующее ключу button $button = $_GET['button']; // выведем строку (ответ сервера) echo $fructs[$button-1]; } ?>
Пример 3. Передача синхронного AJAX запроса на сервер с помощью метода POST
В этом примере данные на сервер будем передавать с помощью метода POST (в теле HTTP-запроса). В методе POST данные (параметры) передаются не в составе URL (метод GET), а в теле, которое мы посылаем серверу через send()
. Т.е. для того чтобы передать данные с помощью POST, мы их должны поместить в качестве параметра методу send()
. Кроме того, при отправке данных с помощью POST необходимо также указать заголовок Content-Type, содержащий кодировку с помощью которой мы зашифровали данные. Это необходимо сделать для того чтобы сервер знал как обработать (расшифровать), пришедшие к нему данные (запрос).
<html lang="ru"> <head> <meta charset="utf-8"> <title>JavaScript AJAX</title> <style> span { font-weight: bold; color: red; } </style> </head> <body> <p>Введите имя и нажмите на кнопку "Получить...".</p> <input id="nameUser" type="text" placeholder="Введите имя"> <input id="button" type="button" value="Получить ответ с сервера"> <p>Ответ (AJAX): <span id="answer"></span></p> <script src="script.js"></script> </body> </html>
// получить элемент, имеющий id="button" var button = document.getElementById("button"); // подпишемся на событие click элемента button.addEventListener("click",function() { // создадим объект XMLHttpRequest var request = new XMLHttpRequest(); // параметры запроса var params = 'name=' + encodeURIComponent(document.getElementById("nameUser").value); // настраиваем запрос: POST - метод, ajaxpost.php - URL-адрес, по которому посылается запрос, false - синхронный запрос request.open('POST','ajaxpost.php',false); // указываем заголовок Content-Type, содержащий кодировку request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // отправляем данные на сервер с помощью метода send request.send(params); // если статус ответа 200 (OK) то if (request.status==200) { // выведем в элемент, имеющий id="answer", ответ сервера document.getElementById("answer").innerHTML = request.responseText; } })
<?php // если в ассоциативном массиве $_POST существует ключ name if (isset($_POST['name'])) { // присвоим переменной $name значение из ассоциативного массива POST соответсвующее ключу name $name = $_POST['name']; // выведем строку (ответ сервера) echo "Привет, ".$name."!"; } ?>
Отличная статья.
Столкнулся с проблемой при попытке сделать отображение прогресса обработки массива PHP обработчиком.
Например, имеем массив:
Вроде решение — которое лежит на поверхности — в цикле отправлять
элементы массива в JSON формате PHP обработчику, пока обработчик чего-то там делает — ждать ответа,
и в случае ответа про «все хорошо» — увеличить прогресс.
Однако, например Google Chrome говорит:
JavaScript console.log causes error: “Synchronous XMLHttpRequest on the main thread is deprecated…”
При чем раз-на-раз не приходится. Когда-то срабатывает, когда-то — выдает ошибку в консоль.
Если делать это асинхронными запросами, то (условно) прогресс стоит на месте до полной обработки
всех элементов и только потом разом стает 100%.
Подскажите. Есть-ли какой-то способ решить эту проблему?