Введение в AJAX и COMET
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/fetch.
В этой главе мы «обзорно», на уровне возможностей и примеров рассмотрим технологию AJAX. Пока что с минимумом технических деталей.
Она будет полезна для понимания, что такое AJAX и с чем его едят.
Что такое AJAX?
AJAX (аббревиатура от «Asynchronous Javascript And Xml») – технология обращения к серверу без перезагрузки страницы.
За счёт этого уменьшается время отклика и веб-приложение по интерактивности больше напоминает десктоп.
Несмотря на то, что в названии технологии присутствует буква X (от слова XML), использовать XML вовсе не обязательно. Под AJAX подразумевают любое общение с сервером без перезагрузки страницы, организованное при помощи JavaScript.
Что я могу сделать с помощью AJAX?
Элементы интерфейса
В первую очередь AJAX полезен для форм и кнопок, связанных с элементарными действиями: добавить в корзину, подписаться, и т.п.
Сейчас – в порядке вещей, что такие действия на сайтах осуществляются без перезагрузки страницы.
Динамическая подгрузка данных
Например, дерево, которое при раскрытии узла запрашивает данные у сервера.
Живой поиск – классический пример использования AJAX, взятый на вооружение современными поисковыми системами.
Пользователь начинает печатать поисковую фразу, а JavaScript предлагает возможные варианты, получая список самых вероятных дополнений с сервера.
Код, который это обеспечивает, работает следующим образом.
- Код активируется примерно при каждом нажатии клавиши, но не чаще чем раз в 100 мс (примерно).
- Текущий результат подсвечен, можно перемещаться и выбирать - При нажатии правой стрелки или при клике -- поиск в подрезультатах 3. Результаты запросов кешируются, повторных обращений к серверу не происходит.
Технически, с помощью AJAX можно обмениваться любыми данными с сервером.
Обычно используются форматы:
- JSON – для отправки и получения структурированных данных, объектов.
- XML – если сервер почему-то работает в формате XML, то можно использовать и его, есть средства.
- HTML/текст – можно и просто загрузить с сервера код HTML или текст для показа на странице.
- Бинарные данные, файлы – гораздо реже, в современных браузерах есть удобные средства для них.
Что такое COMET?
COMET – общий термин, описывающий различные техники получения данных по инициативе сервера.
Можно сказать, что AJAX – это «отправил запрос – получил результат», а COMET – это «непрерывный канал, по которому приходят данные».
- Чат – человек сидит и смотрит, что пишут другие. При этом новые сообщения приходят «сами по себе», он не должен нажимать на кнопку для обновления окна чата.
- Аукцион – человек смотрит на экран и видит, как обновляется текущая ставка за товар.
- Интерфейс редактирования – когда один редактор начинает изменять документ, другие видят информацию об этом. Возможно и совместное редактирование, когда редакторы видят изменения друг друга.
На текущий момент технология COMET удобно реализуется во всех браузерах.
Об этом разделе
Здесь мы будем говорить об AJAX и COMET на низком уровне, на уровне веб-стандартов и их использования.
Существуют библиотеки и фреймворки, добавляющие удобства, например Socket.io, CometD и другие.
В принципе, можно начать их использовать и не зная, что внутри. Но, скорее всего, вам всё равно понадобится отлаживать ошибки, смотреть детали коммуникации, выбирать наилучшее решение для конкретной задачи, и здесь обязательно разбираться, как это всё работает.
Что такое AJAX? Создание асинхронных запросов
В этом уроке разберём создание простых асинхронных AJAX запросов к серверу. На примерах рассмотрим как их выполнить с помощью методов GET и POST. Обработку запросов на стороне сервера выполним с помощью PHP.
Что такое AJAX?
AJAX – это аббревиатура от « A synchronous J avaScript a nd X ML», которая дословно переводится как «асинхронный JavaScript и XML».
Что означают эти слова?
- асинхронный – действие выполняется в фоне (не в основном потоке), другими словами, таким образом, что оно не мешает пользователю взаимодействовать со страницей;
- JavaScript – язык, на котором всё это делается (т.е. создание и настройка запроса, отправка его на сервер, получение ответа и его разбор, обновление страницы);
- XML – формат для хранения и передачи данных, в настоящее время вместо него чаще используется JSON, но кроме них можно использовать и другие форматы.
Что такое AJAX? AJAX – это термин, который описывает как можно используя существующие технологии получать данные с сервера в фоновом режиме и использовать их для обновления страницы (без перезагрузки). Основная цель AJAX – это сделать сайты и веб-приложения более удобными, быстрыми и отзывчивыми.
Основные преимущества использования AJAX:
- снижение трафика (из-за уменьшения объёма передаваемых данных между клиентом и сервером);
- уменьшение нагрузки на сервер (не нужно генерировать всю страницу, а только ту часть, которую нужно обновить);
- увеличение быстродействия и отзывчивости (нет необходимости в полной перезагрузки страницы, достаточно обновить содержимое только отдельных блоков);
- повышение интерактивности (с помощью AJAX можно сразу отображать результаты и сделать ресурс более удобным для пользования).
Взаимодействие с сервером через асинхронные запросы осуществляется посредством XHR или метода fetch() .
Создание асинхронных запросов с помощью XHR
Что такое асинхронный запрос, мы уже разобрали выше. Т.е. это такой, который выполняется в фоне и не мешает пользователю взаимодействовать со страницей. А это значит, что при отправке такого запроса, страница не «замораживается», с ней можно продолжать взаимодействовать.
XHR – это аббревиатура от объекта XMLHttpRequest , который как раз и позволяет взаимодействовать с сервером через AJAX.
Написание запроса можно разбить на следующие этапы.
Этап 1. Создание экземпляра объекта XMLHttpRequest :
JavaScript
const xhr = new XMLHttpRequest();
Этап 2. Инициализация запроса с помощью метода open() :
JavaScript
xhr.open(method, url[, async[, user[, password]]]);
- method – метод отправки запроса на сервер ( GET , POST , PUT , PATCH , DELETE );
- url – URL для отправки запроса;
- async – определяет, как следует выполнять запрос: асинхронно ( true – по умолчанию) или нет ( false );
- user и password – имя пользователя и пароль, использующиеся для аутентификации (по умолчанию имеют значение null ).
JavaScript
// GET – метод, по которому будем делать запрос // requestURL – переменная, содержащая URL для отправки запроса xhr.open('GET', requestURL);
Этап 3. Назначение обработчика на событие readystatechange объекта xhr :
JavaScript
xhr.onreadystatechange = function() { // . }
Это событие происходит при изменении статуса запроса readyState .
readyState – это свойство, содержащее числовой код, по которому можно определить в какой стадии сейчас находится запрос.
Статусы кодов readyState :
- 0 – создан объект XMLHttpRequest , но метод open() ещё не вызывался;
- 1 – открыто новое соединение с помощью open() (этот этап также включает установку значений HTTP заголовкам с помощью setRequestHeader() );
- 2 – отправлен (вызван send() и получены заголовки ответа);
- 3 – получена часть ответа;
- 4 – завершён.
Из всех этих статусов нам интересен только 4. Он будет означать, что ответ от сервера получен и его можно обработать. Остальные коды на практике практически не используются.
Таким образом напишем проверку на равенство значения readyState числу 4:
JavaScript
xhr.onreadystatechange = function() { if (xhr.readyState !== 4) { return; } // все в порядке, ответ получен }
Следующее, что нужно проверить – это статус HTTP-ответа. Он находится в свойстве status .
Если запрос был успешно выполнен сервером, то его статус будет 200. Другие ответы нам в большинстве случаев не интересны. Например, если status равен 404 (запрашиваемый URL не найден), то в этом случае запрашиваемых данных нет и мы можем только как-то обработать эту ошибку.
Кроме кода статуса, нам доступен ещё его текстовый вариант. Получить его можно с помощью statusText .
Добавим ещё одно условие в код: проверку status на равенство 200.
JavaScript
xhr.onreadystatechange = function() // xhr.statusText – текстовый вариант статуса if (xhr.readyState !== 4 // все в порядке, ответ получен и его статус равен 200 }
Теперь, если всё в порядке, мы можем получить данные и делать с ними всё, то угодно.
Получить данные (ответ от сервера) можно осуществляется с помощью xhr.response :
Например, выведем полученный ответ от севера в консоль:
JavaScript
xhr.onreadystatechange = function() if (xhr.readyState !== 4 const response = xhr.response; console.log(response); }
Кроме этого, также имеются ещё xhr.responseText и xhr.responseXML . Они предназначены для получения ответа соответственно в виде строки и объекта XML Document. Они существовали в API раньше и остались по историческим причинам, хотя сейчас в них нет особой необходимости. Т.к. получить ответ можно с помощью xhr.response , а желаемый его тип установить посредством xhr.responseType .
Этап 4. Отправка запроса. Выполняется это с помощью метода send() .
Если запрос асинхронный, то выполнение send() не останавливает дальнейшее выполнение программы. В противном случае (если запрос синхронный), программа приостанавливается и возобновляет своё выполнение только после получения ответа от сервера.
В send() при необходимости можно передать аргумент (данные серверу в теле запроса). Если это не сделать, то по умолчанию будет использоваться значение null .
Запросы GET создаются без тела, все параметры, которые нужно передать серверу здесь указывается в самом URL. Поэтому чтобы тело запроса было пустое, как уже было отмечено выше, нужно вызвать метод send() без аргументов или с аргументом null .
JavaScript
xhr.send();
JavaScript
const xhr = new XMLHttpRequest(); xhr.open('GET', requestURL); xhr.onreadystatechange = function() const response = xhr.response; console.log(response); } xhr.send();
Более современный способ – это вместо readystatechange слушать события load и error :
JavaScript
const xhr = new XMLHttpRequest(); xhr.open('GET', requestURL); // после получения какого-либо ответа от сервера xhr.onload = () => { if (xhr.status !== 200) { // выводим ошибку в консоль console.log(`Ошибка ${xhr.status}: ${xhr.statusText}`); return; } // получаем ответ сервера const response = xhr.response; console.log(response); }; // срабатывает, когда запрос не может быть выполнен (например, нет соединения или не корректный URL) xhr.onerror = () => { // происходит, только когда запрос совсем не получилось выполнить console.log(`Ошибка при выполнении запроса`); }; xhr.send();
Для индикации прогресса загрузки предназначено событие progress :
JavaScript
const xhr = new XMLHttpRequest(); xhr.open('GET', requestURL); xhr.onload = () => { . } // вызывается по мере поступления данных xhr.onprogress = (e) => { // если сервер присылает заголовок Content-Length if (e.lengthComputable) { // e.loaded - количество загруженных байт // e.total - количество байт всего console.log(`Получено ${e.loaded} из ${e.total} байт`); } else { console.log(`Получено ${e.loaded} байт`); } }; xhr.onerror = () => { . }; xhr.send();
Пример AJAX запроса для получения текстовых данных с сервера
В качестве примера напишем асинхронный AJAX запрос на чистом JavaScript, который будет загружать «/examples/ajax/01.html» с сервера в #result :
Пример AJAX GET запроса с параметром
В этом примере напишем асинхронный AJAX запрос, который будет при нажатии на кнопку загружать полученные данные в качестве элементов списка.
1. Для генерации данных на сервере создадим простой php-файл, который будет возвращать массив из определённого количества элементов в формате JSON.
В качестве сервера можно использовать «Open Server Panel», встроенный в PHP веб-сервер, на базе WSL или любой другой.
2. Создадим HTML файл и поместим в следующее содержимое:
- при нажатии на кнопку вызывается функция getData() ;
- эта функция создаёт AJAX запрос и отправляет его на « /examples/ajax/01.php », после получения ответа она обновляет содержимое элемента #list ;
- для преобразования JSON в массив используется метод JSON.parse() ;
- изменение содержимого элемента #list выполняется с помощью innerHTML .
По умолчанию ожидаемым типом ответа ( xhr.responseType ) является строка ( «» ). Но в этом примере мы получаем ответ в формате JSON, поэтому чтобы его распарсить мы дополнительно используем метод JSON.parse() :
JavaScript
// xhr.responseType = ''; // по умолчанию const response = JSON.parse(xhr.response);
Чтобы этого не делать, мы можем с помощью xhr.responseType указать ожидаемый тип ответа. В этом случае скрипт можно переписать так:
JavaScript
xhr.responseType кроме «text» (по умолчанию) и «json» может иметь ещё следующие значения: «arraybuffer» , «blob» и «document» .
Пример синхронного AJAX запроса
Синхронный запрос в отличие от асинхронного, после его отправки и до получения ответа, замораживает веб-страницу, т.е. делает её недоступной для пользователя. Хотя синхронные запросы на сайтах практически не используются, но знать как они создаются лишним не будет.
В качестве примера рассмотрим создания синхронного GET запроса с одним параметром:
Введите ваш вопрос? .
Содержимое файла 04.php:
Пример AJAX POST запроса
Передача данных с помощью метода POST осуществляется в теле запроса. Другими словами, этот метод используется, когда данные нужно передать в скрытом виде. Метод POST очень часто применяется для отправки форм.
$firstname, 'lastname' => $lastname]; exit(json_encode($output));
- Имя: ${response.firstname}
- Фамилия: ${response.lastname}
Более простой способ получить данные формы – это воспользоваться FormData().
Код, приведённый выше в этом случае можно переписать так:
В php дополнительно добавим код для получения IP-адреса:
$firstname, 'lastname' => $lastname, 'ip' => $ip]; exit(json_encode($output));
Если статья понравилась, то поделитесь ей в социальных сетях:
Комментарии: 24
23.03.2021, 16:45
Александр, доброго здоровья!
Будьте добры, подскажите один момент насчет аякс-запросов к стороннему сайту (не локалхост).
$.ajax({ url: "http://. ", method: "POST", timeout: 0, crossDomain:true, data: "{\"sel\":\"production\"}", beforeSend: function(xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa(name+":"+pwd)); }, success: function (data) { console.log(data); } });
В отладчике вызывает ошибку:
«Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at … (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).»
Аналогичная ситуация и при испольозвании
var data = "{\"sel\":\"production\"}"; var xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("readystatechange", function() { if(this.readyState === 4) { console.log(this.responseText); } }); xhr.open("POST", "http://. "); xhr.send(data);
Так как через reqbin.com все работает, прричина все-таки не в настройках сервера?
autotester
22.04.2020, 12:35
У меня на платформе один фрейм и в нем меняются страницы (без перезагрузки). Сейчас возникла проблема, что страница не успевает загрузиться и коллега подсказал проверить ajax запрос, но как это сделать — не знаю. Вручную проблема не воспроизводится, только при автотесте. Можете подсказать, как можно посмотреть эти запросы и понять, где проблема?
Александр Мальцев
22.04.2020, 16:21
Открываете «Инструменты разработчика» в браузере (в Windows комбинация клавиш Ctrl + Shift + I). В ней переходите на вкладку Network, при необходимости можете включить показ только XHR (для этого нужно нажать на соответствующую кнопку на строке Filter), чтобы не показывались другие записи. Далее выбираете нужный скрипт и просматриваете информацию: Headers, Response и т.д. В большинстве случаев этой информации для анализа должно быть достаточно.
09.12.2019, 20:14
Подскажите пожалуйста что специфичное (нестандартное) передается при асинхронных запросах:
— в заголовках от клиента к серверу и обратно
— в данных от клиента к серверу при POST запросе, и от сервера клиенту в блоке данных
Вопрос связан с тем, что HTTP-сервер самописанный и встроен в программу (бинарник), поэтому использовать примеры на PHP не представляется возможным. Cервер работает напрямую с сокетами, делает разбор и формирование заголовков и данных.
Александр Мальцев
10.12.2019, 15:16
Привет! AJAX запросы (синхронные или асинхронные) к серверу ничем не отличаются от обычных. Поэтому если вы не установите с помощью JavaScript дополнительный заголовок, то на сервере вы никак не сможете узнать, что это AJAX. Например, библиотека jQuery устанавливает следующий дополнительный заголовок к запросу: «X-Requested-With: XMLHttpRequest».
10.12.2019, 22:59
Спасибо, Александр, за ваш ответ.
Ваш пример заработал. Действительно, асинхронные запросы прозрачны для сервера.
Моя ошибка была в том, что я выдавал статус 302, а не 200. Это было связано с тем, что нижеприведенный код срабатывал только на статус 302.
24.11.2019, 06:58
Напишите как именно работать с
Получим данные. Если данные посланы через метод GET, то из глобального массива $_GET[‘имя’]. А если данные переданы с помощью метода POST, то из глобального массива $_POST[‘имя’].
Используя эти данные, выполним некоторые действия на сервере. В результате которых получим некоторый ответ. Выведем его с помощью echo.
Александр Мальцев
24.11.2019, 11:23
Тут всё зависит от задачи.
Первое — это нужно получить данные (GET, POST, REQUEST). После этого обычно приступают к проверке данных и того, как они были получены. Если валидация данных прошла не успешно, то действие на сервере обычно прекращают и возвращают результат. В противном случае продолжают дальнейшие действия. Здесь уже вы выполняете действия в зависимости от задачи, опираясь на данные, которые получили. Это может быть выбор информации из базы данных или запись в неё, отправка писем, запись данных в файлы и многое другое. В результате выполнения этого или нет необходимо сформировать ответ и отправить его пользователю. При AJAX формирование ответа обычно осуществляется в формате JSON.
После этого, когда клиент (браузер пользователя) получит ответ от сервера, необходимо его разобрать и вывести пользователю данные или какую-то другую информацию.
Чтобы глубже разобраться в этом разбирайте реальные примеры: Скрипт звёздного рейтинга для сайта, Форма обратной связи и др.
24.11.2019, 14:10
А ваш пример нельзя дополнить, чтобы получить как у вас в статье
так как реально введенное имя назад не возвращается.
Александр Мальцев
24.11.2019, 14:40
Этот момент добавлен к статье.
24.11.2019, 14:47
не работает php не получает введеное имя, соответственно не может вывести (метод post)
24.11.2019, 14:54
myexpedia.ru/%d1%81%d0%ba%d1%80%d0%b8%d0%bf%d1%82/
ps
Еще в ваше статье не корректно работает блок развернуть — перекрывает текст ниже, а должен сдвигать вниз
24.11.2019, 15:31
теперь вообще не работает
12.03.2017, 20:45
Здравствуйте, у меня не получается сделать так, чтобы по нажатию на кнопку изменялась переменная в скрипте php и выводились данные вместо div’а. Сами переменные объявлены в другом куске скрипта.