ВЯЧЕСЛАВ РАДИОНОВ
Ajax: заработавший JavaScript
Уже более 10 лет в Интернете не наблюдалось таких cущественных перемен. Ajax – технология, основанная на JavaScript, которая изменит представление о Всемирной сети. Благодаря ей через несколько лет мы не увидим скучных сайтов, ограниченных в функциональности – интернет-страницы будут иметь такой же внешний вид и возможности, как и современные десктоп-приложения. Похоже, JavaScript дожил наконец до своего звёздного часа.
Технология Ajax, о которой пойдёт речь, медленно, но верно захватывает просторы Интернета. Всем известные примеры, такие как GMail и GoogleMaps – это только цветочки. У новой платформы очень большие амбиции. Сайты, написанные на Ajax, появляются со скоростью, сравнимой со скоростью появления приложений после изобретения микропроцессоров. Именно с технологией Ajax связывают громкую и многообещающую концепцию под названием Web 2.0 (http://www.paulgraham.com/web20.html). Поэтому Ajax стоит как минимум того, чтобы потратить полчаса на изучение основных принципов функционирования и понимания идеи его революционности для Всемирной паутины.
Эволюция Интернета
Для людей, хоть немного имеющих отношение к веб-программированию, уже давно не секрет, что со времён 1995 года, когда появились первые полноценные динамические веб-приложения, Интернет остаётcя по своей сути почти неизменным. Внешне, конечно же, что-то менялось за эти годы: по крайней мере, само наполнение сайтов постоянно трансформировалось и выходило на всё более качественный уровень. Вспомните типичные веб-странички (если кто-то ещё их помнит) конца 90-х годов – ужасные цвета, полное отсутствие стиля, нелепый фон, только мешающий читать текст, и в довершение всего – полная неструктурированность контента. С тех пор очень многое изменилось. Сейчас такие сайты являются максимум поводом для ухмылки и искреннего непонимания, на что вообще рассчитывают авторы этих произведений?
Да, Интернет изменился внешне, и это очень важный шаг вперёд, но суть его осталась прежней. Механизм получения информации клиентом от сервера не менялся. Клиент был вынужден либо ввести URL требуемой страницы непосредственно в адресную строку своего браузера, либо ввести тот же URL косвенно, заполнив данные формы и отправив их серверу на обработку. В любом случае пользователю приходилось проводить некоторое время в бездействии, сидя перед пустым или постепенно заполняющимся экраном. Минусов у такого подхода очень много, ведь пользователь, особенно в нашей стране, не всегда имеет достаточно быстрый канал, чтобы постоянно гонять поток килобайтов по сети туда и обратно, кроме того, новая страничка зачастую более чем на 90% состоит из информации, которую вы уже загружали раньше. Выходит, что, кроме времени, вы ещё и впустую тратите свои деньги за трафик. Всех этих минусов лишён подход написания страниц, использующий технологию Ajax.
Зачем нужен Ajax
Что же обещает нам новая платформа? Чтобы понять это, нужно не только овладеть принципами Ajax, но и узнать причины, которые привели к созданию данной технологии.
Рынок клиентских компьютерных приложений имеет классическое разделение на два сектора: рынок десктоп-приложений и рынок веб-приложений. Каждое из этих направлений до недавнего времени имело свои ярко выраженные особенности, свои плюсы и свои минусы, которые исключали возможность появления программы, которую можно было бы назвать как полноценным десктоп-приложением, так и полноценным веб-приложением. Программы, ориентированные на десктоп, как правило, привязаны к конкретной операционной системе, они часто имеют внушительные размеры и системные требования и необходима процедура установки на компьютер пользователя. Они часто отличаются красивым и очень функциональным интерфейсом, который позволяет не только кликать по областям приложения и вводить текст, но и переносить объекты из одного приложения в другое и пользоваться удобными меню. Кроме того, всё это происходит без значительных задержек и не заставляет пользователя долго ждать реакции приложения на его действия. Десктоп-приложения выполняются на машине пользователя и оперируют в основном локальными данными (исключение составляют так называемые «толстые» клиенты, которые, тем не менее, остаются десктоп-приложениями). В последнее время десктоп-приложения всё чаще поддерживают систему обновления через Интернет, которая хоть и значительно улучшает процесс приобретения новых версий, что крайне важно для таких приложений, как антивирусы, тем не менее является довольно долгой и сложной для конечного пользователя процедурой. Веб-приложения, напротив, отличаются крайне малыми размерами, хранятся на удаленном сервере, не требуя для себя места на жёстком диске клиента, и даже не имеют возможности воспользоваться данными, расположенными на компьютере пользователя. Эти приложения имеют, как правило, довольно однотипный интерфейс, который не отличается особой вычурностью и функциональностью. С другой стороны, веб-приложения всегда доступны вам в своей последней возможной версии и не требуют от вас никаких усилий по установке и поддержке, предоставляя возможности, которые недоступны при пользовании десктоп-приложениями (такие, как участие во всевозможных конференциях и форумах, поиск информации по всему миру, участие в онлайн-аукционах и прочие возможности).
Так продолжалось очень долго, и рано или поздно ситуация должна была измениться. Почти незаметно на сцену вышла новая технология, которая, как вы увидите позже, на самом деле оказалась удачным совместным использованием уже существующих платформ. Эта технология призвана если не стереть, то по крайней мере размыть границу между десктоп- и веб-приложениями.
Ajax в действии
Давайте наконец посмотрим, из чего состоит Ajax. Технология Ajax является совместным использованием таких технологий, как:
- HTML (а точнее, XHTML) и CSS – языки, которые необходимы, как и прежде, для визуального представления данных приложения пользователю.
- JavaScript – язык, который является основной движущей силой Ajax и который отвечает за взаимодействие между клиентом и сервером.
- DHTML – динамический HTML, технология, которая помогает обновлять компоненты страницы динамически, не перегружая саму страничку.
- XML – собственно язык, на котором в Ajax общаются сервер и клиент и который является «материалом» для построения сайта.
- DOM – объектная модель документа, технология, которая нужна как для обработки и управления структурой сайта (HTML), так и для обработки возвращаемых сервером данных (XML).
Кстати, само название Ajax имеет определённый смысл, это сокращение от «Asynchronous JavaScript and XML» (асинхронный JavaScript и XML). Данная аббревиатура была введена Джессом Джеймсом Гарреттом (Jesse James Garrett) из Adaptive Path в статье, впервые описавшей собственно саму технологию Ajax.
Как видите, все технологии существуют не первый день и достаточно хорошо известны любому современному программисту. Основной трюк при написании Ajax-приложения – это использование объекта XMLHttpRequest. Как бы странно это ни звучало, но этот объект – то единственное новшество, которое есть в Ajax. Никаких других новых технологий в этой платформе нет. Но, как оказалось, и этого вполне достаточно для того, чтобы в корне изменить поведение веб-приложений. Так что давайте перейдём к непосредственному написанию кода, чтобы понять, как работает этот самый объект, который вызвал такой ажиотаж.
Чтобы написать Ajax-приложение, нам понадобится создать экземпляр объекта XMLHttpRequest. В случае, соответствующем стандартам программирования, это будет выглядеть так:
<script language="javascript" type="text/javascipt">
var xmlhttp = new XMLHttpRequest();
</script>
Как всегда, этот пример будет работать везде, кроме браузера компании Microsoft – Internet Explorer. Эти традиции неизменны с 1995 года и, как всегда, мы должны обрабатывать отдельно случай IE и случай не-IE. Но об этом ещё пойдёт речь.
Рассмотрим стандартный механизм. Обычно пользователь, чтобы совершить какое-либо действие на странице, должен фактически заполнить некоторую форму, отправить её серверу, тот должен обработать и вернуть новую страничку браузеру, который отобразит её вместо текущей. Именно этот механизм мы и собираемся изменить. Вместо ожидания новой страницы от сервера мы собираемся передать данные из формы на обработку JavaScript-функции. После этого из объекта xmlhttp будет сформирован и отправлен запрос к серверу. Важное отличие такого подхода заключается в том, что процесс отсылки данных пройдёт незаметно для пользователя. Он сможет продолжать перемещаться по страничке и даже использовать Javascript-функции. А когда от сервера придут данные, то опять же с помощью Javascript-функционала будет решено, что с этими данными делать, и изменения можно будет внести в страничку без перезагрузки, просто добавив, убрав или изменив определённые элементы в объектной модели документа.
Рассмотрим этот механизм подробнее на примере простейшего Ajax-приложения.
<script language="javascript" type="text/javascipt">
function connectServer(){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", "http://ourserver.org/ajax_service.php",true);
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4) {
var xmlData = this.responseText;
//здесь идёт обработка полученных данных
}
}
xmlHttp.overrideMimeType('text/xml');
xmlHttp.send(null);
}
</script>
Возможно, код немного напугал вас своей экстравагантностью, но не спешите закрывать статью. Сейчас мы поймём, что всё написано абсолютно логично и чётко, а главное, просто. Первая непонятная строчка выглядит так:
xmlHttp.open("GET", "http://ourserver.org/ajax_service.php",true);
Здесь мы вызываем метод open, необходимый для установления соединения между нашим объектом XMLHttpRequest и сервером. Первый параметр указывает на метод передачи данных («POST» и «HEAD» тоже можно использовать, но мы пока этого случая касаться не будем), второй – на URL, которому отправляется запрос, и от которого приходит ответ. Третий параметр устанавливает режим асинхронной передачи данных. Это значит, что работа веб-приложения не будет остановлена в ожидании ответа сервера. Наоборот, в поведении странички ровным счётом ничего не изменится, и только тогда, когда придет ответ от сервера, мы увидим изменения.
У людей, не владеющих тонкостями JavaScript, наверняка вызвали беспокойство строчки:
xmlHttp.onreadystatechange = function(){
if (xmlHttp.readyState == 4) {
var xmlData = this.responseText;
//здесь идёт обработка полученных данных
}
}
Думаю, будет проще это понять, если вы немного знакомы с объектно-ориентированным программированием и технологией обратного вызова. Но даже в случае, если об ООП вы только слышали, то нетрудно понять, что всё, что мы делаем, – это назначаем функцию, которая будет вызываться при поступлении данных от сервера. Следует знать и понимать, что this во время вызова функции onreadystatechange (функции обратного вызова) будет объектом xmlHttp, а responseText будет соотвественно переменной этого объекта, в которую будет помещён ответ сервера. Тонкость в том, что мы не знаем, когда именно ждать ответа сервера, поэтому мы не будем его ждать вообще, вместо этого, когда придет ответ, то произойдёт 3 события: будет изменено состояние объекта xmlHttp (xmlHttp.readyState), ответ будет помещён в переменную xmlHttp.responseText и будет вызвана функция xmlHttp.onreadystatechange().
Надеюсь, механизм прояснился более или менее. Осталось лишь одно тёмное место – состояния объекта. Что же это такое?
В общем-то, ничего сложного. Просто для того, чтобы мы могли узнать, что и когда делать, объект xmlHttp имеет 5 состояний:
- 0 – «uninitialized» – объект не инициализирован;
- 1 – «loading» – объект подгружает свои данные;
- 2 – «loaded» – объект загружен;
- 3 – «interactive» – можно работать, хотя ещё не весь ответ сервера прочитан;
- 4 – «complete» – можно работать, всё загружено.
Пока что нас интересует только состояние 4. Его мы и обрабатываем.
Рассмотрим код дальше. Осталось самое простое:
xmlHttp.overrideMimeType('text/xml');
xmlHttp.send(null);
В первой строчке мы говорим серверу о том, что хотим получить ответ, соответствующий mime-типу text/xml. Это своего рода формальность, так как не все браузеры умеют обрабатывать ответ сервера только в строго определённом формате. Вторая строчка – это собственно отправка данных на сервер. Аргументом являются параметры, отправляемые серверу, если мы используем метод «POST» для передачи данных. Так как мы отсылаем GETзапрос, то и передавать ничего не будем.
В нашем примере мы вообще не передаём никаких параметров, но если бы мы этого хотели, то в вызов xmlHttp.open следовало бы вставить стандартный GET-запрос вида http://ourserver.org/ajax_service.php?name=foo&value=bar. В примере, в конце статьи мы так и поступим.
Итак, теперь вы знакомы с базовым механизмом работы Ajax-приложения. Осталось написать программу, которая будет иметь какой-либо практический смысл, пусть даже совершенно условный.
Напишем приложение для проверки почты в системе Gmail:
<html>
<head>
<meta HTTP-EQUIV="content-type"
CONTENT="text/html; charset=UTF-8">
<title>Проверка почты с помощью новейших технологий</title>
</head>
<body>
<script language="javascript" type="text/javascript">
var xmlHttp = false;
function callServer(name, password) {
try {
netscape.security.PrivilegeManager.
enablePrivilege("UniversalBrowserRead");
} catch (e) {
alert("Недостаточно прав, чтобы использовать Ajax!");
}
//обычный браузер
if (window.XMLHttpRequest) {
try {
xmlHttp = new XMLHttpRequest();
} catch(e) {
xmlHttp = false;
}
} else
/ случай IE
if (window.ActiveXObject) {
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xmlHttp = false;
}
}
}
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
var xmlData = xmlHttp.responseText;
var xmlobject = (new DOMParser()).parseFromString(xmlData, "text/xml");
var root = xmlobject.getElementsByTagName('feed')[0];
var number = root.getElementsByTagName("fullcount");
alert(name+ ", количество писем в вашем ящике: " + number[0].firstChild.nodeValue);
}
}
xmlHttp.open('GET', 'https://'+name+':'+password+'@gmail.google.com/gmail/feed/atom', true);
xmlHttp.overrideMimeType('text/xml');
xmlHttp.send(null);
}
</script>
<form name='gmail'>
Имя: <input name="name" type="text">
Пароль: <input name="password" type="password"> <br />
<a href="#" onclick="nojavascript...callServer(gmail.name.value, gmail.name.password);">Проверить почту</a>
</form>
</body>
</html>
Посмотрим, что нового здесь появилось. Во-первых, следует вас предупредить, что по умолчанию ваш браузер не позволит загрузить данные с нелокального ресурса. Поэтому мы попробуем изменить свои привилегии для доступа к данным Gmail:
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
Во-вторых, не обращайте внимание на усложнившуюся схему получения объекта XMLHttpRequest, она нужна лишь для того, чтобы скрипт работал и в Internet Explorer. Кстати, скрипт следует запускать именно с локальной машины (не сервера), потому как иначе браузер не разрешит вам обратиться с одного сервера к другому.
Следующее, что может быть непонятно, – это строки:
var xmlobject = (new DOMParser()).parseFromString(xmlData, "text/xml");
var root = xmlobject.getElementsByTagName('feed')[0];
var number = root.getElementsByTagName("fullcount");
alert(name+ ", количество писем в вашем ящике: " + number[0].firstChild.nodeValue);
Здесь мы используем DOM-модель документа для прохода по xml-дереву полученных от сервера данных. Ищем корневой элемент <feed>...</feed> (getElementsByTagName(‘feed’)), затем в нём находим тэг <fullcount></fullcount> (getElementsByTagName(“fullcount”)) и выводим значение, которое находится в этом тэге (number[0].firstChild.nodeValue). Изначальный xml-код выглядит примерно так:
<feed version="0.3">
<title>Gmail - Inbox for Vasya_Pupkin@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>1</fullcount>
<link rel="alternate" href="http://mail.google.com/mail"type="text/html"/>
...
</feed>
Чтобы скрипт корректно работал на вашей машине, желательно иметь Mozilla-совместимый браузер и быть авторизованным в системе GMail (http://gmail.com).
Заключение
Мы разобрались с основами Ajax, с самым базовым функционалом, который использует любое ajax-приложение. В следующих статьях я постараюсь показать всю мощь этой технологии. Будет рассказано о таких вещах, как соединение с SQL-сервером, создание оконного интерфейса с поддержкой техники Drag&Drop. Вы узнаете о доступных фреймворках и различных средах разработки, позволяющих значительно упростить жизнь ajax-разработчика.
Напоследок, чтобы еще больше подогреть ваш интерес к этой замечательной технологии, приведу несколько ссылок наиболее впечатляющих проектов, выполненных с помощью Ajax.
Ссылки:
- http://www.backbase.com/demos/RSS – Backbase Ajax RSS reader, «читалка» RSS-лент новостей. Пока что в демо-режиме, но посмотреть на это стоит.
- http://www.squarefree.com/htmledit – Real-time HTML Editor, позволяет редактировать HTML-код и одновременно его просматривать.
- http://www.unwieldy.net/ajaxim – icq- и jabber-подобный клиент для обмена сообщениями. Пока что тоже только в демо-режиме.
- http://demo.primalgrasp.com/spell/check_spelling – проверка орфографии, не выходя из браузера.
- http://code.jalenack.com/periodic – таблица Менделеева.