В этой статье AJAX описывается на уровне возможностей и примеров. Рассмотрены особенности асинхронного взаимодействия и примеры использования, но с минимумом технических деталей.
Надеюсь, она будет полезна для понимания, что такое AJAX и с чем его едят.
AJAX, или, более длинно, Asynchronous Javascript And Xml - технология для взаимодействия с сервером без перезагрузки страниц.
За счет этого уменьшается время отклика и веб-приложение по интерактивности больше напоминает десктоп.
Например, при нажатии кнопки голосовать - из браузера на сервер будет отправлено сообщение, а сервер ответит браузеру, что голос принят.

Технология AJAX, как указывает первая буква A в ее названии - асинхронна, т.е браузер, отослав запрос, может делать что угодно, например, показать сообщение
об ожидании ответа, прокручивать страницу, и т.п.
Вот код кнопки в примере выше:
<input value="Голосовать!" onclick="vote()" type="button" />
При нажатии она вызывает функцию vote, которая отправляет запрос на сервер, ждет ответа, а затем показывает сообщение об этом в div'е под кнопкой:
<div id="vote_status">Здесь будет ответ сервера</div>
Далее мы разберем, как она работает, более подробно.
Для обмена данными с сервером используется специальный объект XmlHttpRequest, который умеет отправлять запрос и получать ответ с сервера. Кроссбраузерно создать такой объект можно, например, так:
function getXmlHttp(){
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
Более подробно о деталях реализации AJAX с использованием XmlHttpRequest и других транспортов можно почитать в разделе про общение с сервером.
Здесь мы не будем на этом останавливаться и перейдем сразу к функции vote:
// javascript-код голосования из примера
function vote() {
// (1) создать объект для запроса к серверу
var req = getXmlHttp()
// (2)
// span рядом с кнопкой
// в нем будем отображать ход выполнения
var statusElem = document.getElementById('vote_status')
req.onreadystatechange = function() {
// onreadystatechange активируется при получении ответа сервера
if (req.readyState == 4) {
// если запрос закончил выполняться
statusElem.innerHTML = req.statusText // показать статус (Not Found, ОК..)
if(req.status == 200) {
// если статус 200 (ОК) - выдать ответ пользователю
alert("Ответ сервера: "+req.responseText);
}
// тут можно добавить else с обработкой ошибок запроса
}
}
// (3) задать адрес подключения
req.open('GET', '/ajax_intro/vote.php', true);
// объект запроса подготовлен: указан адрес и создана функция onreadystatechange
// для обработки ответа сервера
// (4)
req.send(null); // отослать запрос
// (5)
statusElem.innerHTML = 'Ожидаю ответа сервера...'
}
Поток выполнения, использованный vote, довольно типичен и выглядит так:
XmlHttpRequestonreadystatechangeopensend (ответ сервера принимается срабатывающей в асинхронном режиме функцией onreadystatechange)Серверный обработчик, к которому обращен AJAX-запрос (в примере это vote.php) по сути ничем не отличается от обычной страницы. AJAX-запрос, отправляемый XmlHttpRequest, ничем не отличается от обычного запроса.
Просто текст, который возвращает сервер, не показывается как HTML, а читается и обрабатывается функцией onreadystatechange.
<?php sleep(3); echo 'Ваш голос принят!';
Технология AJAX использует комбинацию:
транспорт.
Типичное AJAX-приложение состоит как минимум из двух частей.
Первая выполняется в браузере и написана, как правило, на JavaScript, а вторая - находится на сервере и написана, например, на Ruby, Java или PHP
.
Между этими двумя частями происходит обмен данными через XMLHttpRequest(или другой транспорт).
Смысл AJAX - в интерактивности и быстром времени отклика.
В первую очередь AJAX полезен для небольших элементов, связанных с элементарными действиями: добавить в корзину, подписаться, и т.п.
![]() |
![]() |
![]() |
Например, дерево, узлы которого подгружаются по мере раскрытия.
Бесконечное деревоНапример, при редактировании статьи - каждые 10 минут результаты автосохраняются на сервере.
Самый типичный пример - чат. В окошко постоянно поступают все новые сообщения, непрерывно подгружаемые с сервера. И, опять же, через AJAX, без перезагрузки страницы, пользователь может
отсылать сообщения на сервер.
Существуют другие предложения подобного рода, например, отображающие биржевые котировки в реальном времени.
Google - одна из первых систем, которая предложила "живой поиск", live search. Пользователь печатает поисковую фразу, а система автодополняет ее, получая
список самых вероятных дополнений с сервера.

Код, который это обеспечивает, работает следующим образом.
Раз уж взялись за Google - рассмотрим почтовый сервис той же компании, http://gmail.com.
На момент его появления он явился единственным открытым почтовым сервисом, использующим AJAX для следующих фич.
Результат: обширная популярность, высокий спрос на account'ы с момента открытия.
В обычном программировании все операции носят синхронный характер, т.е выполняются одна за другой.
Условно говоря, мы действуем так:
При асинхронном подходе мы:
Т.е, в синхронном случае удочка постоянно приковывает наше внимание. Ловля рыбы - последовательный процесс.
В асинхронном варианте - мы сначала задали программу, что делать при клеве, а затем опустили удочку ловить и занялись другими делами.
Например, поставили еще 5 таких удочек.
Асинхронное программирование сложнее, чем синхронное, и поначалу непривычно, т.к в нем заранее задается то, что сработает после.
Т.е, программу "что делать, когда клюнет" нужно задать до того, как клюнуло, и вообще неизвестно, есть ли в водоеме рыба.
Существуют приемы, облегчающие асинхронное программирование, например, отложенный объект Deferred (Twisted,Dojo,Mochikit), но об этом - в отдельной статье.
Вернемся к нашим баранам: браузеру, серверу и, скажем, базе данных.
В синхронной модели браузер отправляет запрос на сервер и висит, ждет, пока тот совершит всю необходимую работу. Сервер выполняет запросы к базе данных, заворачивает ответ в необходимый формат и выводит его. Браузер. получив ответ, вызывает функцию показа.
Все процессы выполняются последовательно, один за другим.
Сетевые задержки включены во время ожидания, обозначенное на схеме серым цветом.
Пользователь не может заниматься чем-то другим на этой же странице, пока происходит синхронный обмен данными.

В асинхронной модели запрос отсылается ("удочка поставлена"), и можно заняться чем-то другим. Когда запрос выполнился ("клюнуло") - запускается заранее
подготовленная программистом функция ("подтянуть спиннинг") показа сообщения сервера.

Здесь сервер сразу же уведомляет браузер о том, что запрос принят в обработку и освобождает его для дальнейшей работы. Когда ответ будет готов - сервер перешлет его, и на браузере будет вызвана соответствующая функция показа, но пока этот ответ формируется и пересылается - браузер свободен.
Пользователь может написать комментарии, заполнить и отослать форму и т.п: Могут производиться новые асинхронные запросы.
Асинхронная модель характеризуется почти мгновенной реакцией на действия пользователя, так что создается впечатление удобного и быстрого приложения.
Например, в примере с голосованием выше - кнопка срабатывает сразу, хотя реальный учет голоса происходит позднее, после обработки сообщения сервером.
Из-за такого разрыва между действием и реальным результатом приложение становится гораздо более чувствительно к ошибкам.
Особенно в случае нескольких одновременных асинхронных запросов, нужно заботиться об очередности выполнения и ответа (race-conditions) и, в случае ошибки, оставлять приложение в целостном (consistent) состоянии.
Плюсов всего два, зато какие! Овчинка стоит выделки.
Иногда для асинхронных операций необходимо делать различные "финты ушами". Например, хочется сделать drag'n'drop в дереве, т.е перетаскивать статьи из одного раздела в другой мышкой, и чтобы они на сервере в базе данных меняли родителя.
Drag'n'drop - это "взял мышей объект - положил куда надо - готово". Но в асинхронной модели не может быть все прям сразу "готово".
Надо проверить привилегии на сервере, проверить, существует ли еще объект, вдруг его удалил другой пользователь.
Надо как-то показать, что процесс пошел, но результат "ща будет..". А как? В асинхронной модели указатель мыши не может просто так зависнуть над объектом, превратившись в часики.
В таком случае применяют либо синхронные запросы к серверу - и тогда все действительно подвисает, либо оригинальный выход - положить объект, как будто он перенесен, и проинформировать анимированной иконкой об ожидании ответа.
Если ответ отрицателен - обработчик ответа переносит объект обратно.
В примере с drag'n'drop также затронута проблема "stale context" - устаревшего контекста.
Веб - многопользовательская среда. Если для навигации используется,
скажем, дерево статей, то над ним работают много человек. Один из них может удалить ветку дерева, над которой работает другой: конфликт.
Как правило, для преодоления таких казусов используются следующие средства:
Это когда все знают кто чего делает и на уровне деления полномочий и личного общения такие удаления согласовывают. Вариант заведомо небезопасный, но обычно работающий.
Локинг - блокирование редактируемых документов.
Версионный контроль - каждый новый документ становится версией, так что изменения никогда не теряются. Версионность влечет за собой конфликты, когда Петя начал редактировать документ раньше Васи, а сохранил - позже. При этом в последней версии изменения Васи оказались потеряны, хотя предпоследняя (Васина) версия в системе обязательно есть.
Более подробно о локинге и версионности можно почитать, например, в документации к системе версионного контроля Subversion.
Проблема устаревшего контента может быть на 99% решена при помощи мгновенного автообновления.
Браузер держит постоянное соединение с сервером (или делает время от времени корректирующие запросы) - и нужные изменения отсылаются по этому каналу.
Например, в раскрытую ветку дерева иногда подгружаются новые статьи, в открытый почтовый интерфейс - новые письма.
Вообще, проблема устаревшего контекста напрямую относится к задаче целостности данных. За конечную проверку целостности, как и при валидации форм, в любом случае несет ответственность сервер.