Изучаем Java

Вы здесь: Главная >> Jquery-учебник >> Делаем первое приложение на AJAX

Делаем первое приложение на AJAX


Ну а сейчас мы с вами создадим первое простейшее приложение на AJAX.

Здесь вы создадите простое вебприложение под названием quickstart, применяя технологию AJAX. Оно запрашивает у пользователя имя и по мере ввода сервер возвращает клиенту полученные от него данные.

Пока пользователь вводит свое имя, через регулярные интервалы времени производятся обращения к серверу, чтобы он мог опознать текущее имя. Сервер вызывается автоматически, примерно один раз в секунду, и поэтому на форме отсутствует кнопка «Передать» (Submit), с помощью которой производится передача данных серверу в классических вебприложениях. (Такой метод плохо подходит для реализации механизмов авторизации пользователей, но он прекрасно демонстрирует некоторые возможности AJAX.)

На первый взгляд в этом приложении нет ничего экстраординарного. Мы нарочно сохранили простоту первого примера, чтобы вам было проще разобраться в нем. Примечательно в этом приложении то, что отображаемое сообщение автоматически поступает от сервера, не прерывая действий пользователя. (Сообщение появляется сразу же, как только пользователь начинает вводить свое имя.) Для того чтобы отобразить сообщение, приложение не производит повторную загрузку всей страницы, даже несмотря на то, что за получением текста сообщения необходимо обращаться к серверу. Без помощи AJAX достигнуть такого эффекта очень сложно.

Приложение состоит из трех файлов:

- index.html  файл HTML, который изначально запрашивает пользователь.

- quickstart.js  файл, содержащий код JavaScript, который загружается клиентом вместе с index, html. Этот файл отвечает за выполнение асинхронных обращений к серверу, когда становится необходимой его функциональность.

- quickstart.php  сценарий РНР, постоянно находящийся на сервере. Этот сценарий вызывается со стороны клиента из кода JavaScript, находящегося в файле quickstart.js.

Примеры кода

<!DOCTYPE html PUBLIC "//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 
   AJAX with PHP: Quickstart
   
 
 
    Server wants to know your name:
    <input id="myName" type="text">
   

 


 
</html>

index.htm

// stores the reference to the XMLHttpRequest object
var xmlHttp = createXmlHttpRequestObject();

// retrieves the XMLHttpRequest object
function createXmlHttpRequestObject()
{         
  // will store the reference to the XMLHttpRequest object
  var xmlHttp;
  // if running Internet Explorer
  if(window.ActiveXObject)
  {
    try
    {
      xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    catch (e)
    {
      xmlHttp = false;
    }
  }
  // if running Mozilla or other browsers
  else
  {
    try
    {
      xmlHttp = new XMLHttpRequest();
    }
    catch (e)
    {
      xmlHttp = false;
    }
  }
  // return the created object or display an error message
  if (!xmlHttp)
 
    alert("Error creating the XMLHttpRequest object.");
  else
    return xmlHttp;
}

// make asynchronous HTTP request using the XMLHttpRequest object
function process()
{
  // proceed only if the xmlHttp object isnt busy
  if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
  {
    // retrieve the name typed by the user on the form
    name = encodeURIComponent(document.getElementById("myName").value);
    // execute the quickstart.php page from the server
    xmlHttp.open("GET", "quickstart.php?name=" + name, true); 
    // define the method to handle server responses
    xmlHttp.onreadystatechange = handleServerResponse;
    // make the server request
    xmlHttp.send(null);
  }
  else
    // if the connection is busy, try again after one second 
    setTimeout(`process()`, 1000);
}

// executed automatically when a message is received from the server
function handleServerResponse()
{
  // move forward only if the transaction has completed
  if (xmlHttp.readyState == 4)
  {
    // status of 200 indicates the transaction completed successfully
    if (xmlHttp.status == 200)
    {
      // extract the XML retrieved from the server
      xmlResponse = xmlHttp.responseXML;
      // obtain the document element (the root element) of the XML structure
      xmlDocumentElement = xmlResponse.documentElement;
      // get the text message, which is in the first child of
      // the the document element
      helloMessage = xmlDocumentElement.firstChild.data;
      // update the client display using the data received from the server
      document.getElementById("divMessage").innerHTML =
                                            `` + helloMessage + ``;
      // restart sequence
      setTimeout(`process()`, 1000);
    }
    // a HTTP status different than 200 signals an error
    else
    {
      alert("There was a problem accessing the server: " + xmlHttp.statusText);
    }
  }
}

quickstart.js

<?php
// well generate XML output
header(`ContentType: text/xml`);
// generate XML header
echo `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`;
// create the <response> element
echo `<response>`;
 
// retrieve the user name
$name = $_GET[`name`];
// generate output depending on the user name received from client
$userNames = array(`CRISTIAN`, `BOGDAN`, `FILIP`, `MIHAI`, `YODA`);
if (in_array(strtoupper($name), $userNames))
  echo `Hello, master ` . htmlentities($name) . `!`;
else if (trim($name) == ``)
  echo `Stranger, please tell me your name!`;
else
  echo htmlentities($name) . `, I dont know you!`;
// close the <response> element
echo `</response>`;
?>

quickstart.php

 

А теперь давайте опишем процессы, происходящие в нашем первом Ajax  приложении

1. Пользователь в помощью веббраузера запрашивает страницу index.html
2. Веббраузер посылает вебсерверу обычный запрос HTTP, чтобы получить файл index.html
3. Сервер отвечает на запрос и отправляет обратно файл index.html
4. Клиент загружает файл index.html, компонует страницу и выводит на экран
5. Получив страницу, пользователь начинает ввод своего имени.
6. Сценарий quickstart.js выполняет асинхронное обращение к сценарию quickstart.php, расположенному на сервере.
7. Сервер запускает сценарий quickstart.php и возвращает результаты его работы в формате XML
8. Сценарий quickstart.js получает ответ от сервера и обновляет текст сообщения.
9. Сообщение на странице обновляется, в то время как пользователь продолжает работу со страницей
10. Перейти к п.5

 

Шаги с 1 по 5  это типичный запрос HTTP. После того как запрос будет послан, пользователю придется подождать, пока загрузится страница. В случае типичных вебприложений (не использующих технологию AJAX) такая загрузка страницы происходит всякий раз, когда клиент пытается получить новые данные от сервера.

Шаги с 5 по 9 демонстрируют запрос AJAX, а если точнее, то целую серию асинхронных запросов HTTP. Доступ к серверу производится в фоновом режиме, с помощью объекта XMLHttpRequest. В это время пользователь может продолжать нормальную работу со страницей, как если бы это было обычное приложение. Чтобы получить новые данные от сервера и обновить текст сообщения на странице, не надо загружать страницу повторно.

 

 

Пояснения к коду примера

Разберемся с тем, что делает наш код.

Начнем с файла, который первым встречается пользователю,  index.html. Этот файл содержит ссылку на файл JavaScript с именем quickstart.js и создает очень простенький вебинтерфейс для клиента

<body onload=`process()`>
    Server wants to know your name:
    <input id="myName" type="text" >
   

 


 

После загрузки страницы вызывается функция process() из файла quickstart.js. Она заполняет элемент div сообщением, полученным от сервера.

Прежде чем рассматривать, что происходит внутри функции process(), мы узнаем, что происходит на стороне сервера. На вебсервере находится сценарий quickstart.php, который собирает сообщение в формате XML и отправляет его клиенту. Это сообщение содержит элемент response, в который упакован текст сообщения:

<?xml version="1.0" encoding="UTF-8"
standalone="yes"?> <response>
... текст сообщения, отправляемого клиенту ...
</response>

Если в качестве имени пользователя сервер получил пустую строку, то в качестве сообщения будет отправлен текст: «Скажи мне, как тебя зовут, незнакомец!». Если сервер получит имя, одно из пяти: Cristian, Bogdan, Filip, Mihai или Yoda, сервер ответит: «Здравствуйте, мастер “имя пользователя”. Если будет получено какоелибо другое имя, сервер ответит сообщением: “имя пользователя” вы мне не знакомы!”.
Так, если Микки Маус введет свое имя, сервер отправит следующую структуру XML:

<?xml version="1.0" encoding="UTF-8"
standalone="yes"?> <response>
Микки Маус, вы мне не знакомы!
</response>

Сценарий quickstart.php начинает с генерации заголовка документа в формате XML и открытия элемента responses

<?php
// результаты будем отправлять в формате
XML header( `ContentType: text/`);
// сгенерировать заголовок XML
echo `<?xml version="l.O" encoding="UTF-8" standalone="yes"?>`;
// создать элемент <response>
echo `<response>`;

Выделенная строка сообщает о том, что выходные данные представляют собой документ XML. Это очень важно, поскольку клиент ожидает получить ответ от сервера в формате XML (прикладной программный интерфейс на стороне клиента сгенерирует ошибку, если в заголовке ContentType не будет содержаться значение text/xml). После настройки заголовка код собирает ответ путем выполнения слияния строк. Фактический текст сообщения, который будет отправлен клиенту, заключается в элемент responses корневой элемент, а само сообщение генерируется на основе имени, полученного от клиента через параметр GET:

Текст, введенный пользователем (предполагается, что это его имя), клиент отправляет серверу через параметр GET. Когда сервер передает имя обратно клиенту, мы вызываем функцию РНР htmlentities(), которая замещает служебные символы (такие как & ) их HTMLаналогами, тем самым гарантируя безопасное отображение их вебброузером и устраняя потенциальные неприятности.

 

Примечание

Форматирование текста, предназначенного для клиента, на стороне сервера (вместо того, чтобы делать это на стороне клиента)  это плохая практика. В идеале сервер должен возвращать клиентам данные в обобщенном формате, а уже клиент должен побеспокоиться о форматировании и безопасности. Такое положение вещей обретает еще больший смысл, если вы только представите, что когда-либо в будущем вам придется вставлять текст ответа, например, в базу данных, но база данных требует добавления иных форматирующих последовательностей (в этом случае точно так же о форматировании должен беспокоиться сценарий на стороне базы данных, но никак не сервер). В случае с приложением quickstart форматирование кода HTML в сценарии РНР вполне допустимо, поскольку это обеспечивает простоту нашего примера и облегчает его изучение.

Если вы испытываете желание протестировать сценарий quickstart, php и увидеть, что он возвращает, установите в броузере в адресном поле значение http://localhost/ajax/quickstart/quickstart.php?name=Yoda. Преимущество передачи параметров от клиента методом GET состоит в том, что такие запросы легко эмулируются с помощью броузера, поскольку в этом случае достаточно добавить параметры в виде пар имя/значение в конец строки запроса.

Это сообщение в формате XML клиент получает с помощью функции handleServerftesponse(), которая находится в файле quickstart.js. Точнее говоря, текст сообщения “Привет, мастер YodaU” извлекается следующей частью кода:

// извлечь XHL, полученный от сервера
xmlResponse = xmlHttp.responseXHL;
// получить корневой элемент в структуре XML
xmlDocumentElement = xmlBesponse.documentElement;
// извлечь текстовое сообщение, которое находится в первом
// дочернем элементе корневого узла
helloMessage = xmlOocunentElement.firstChild.data;

Здесь переменная xmlHttp представляет собой ссылку на объект XMLHttpRequist, который в сценарии quickstart.js служит для передачи запросов серверу. Свойство responseXML этого объекта извлекает полученный XMLдокумент, имеющий иерархическую структуру, а корневой элемент документа XML называется элементом документа. В нашем случае корневым является элемент responses который имеет единственного потомка  текст интересующего нас сообщения. После того как текст будет извлечен, он отображается на странице, благодаря использованию DOM для доступа к элементу divMessage, находящемуся в файле index.html

// обновить текст сообщения на экране
document.getElementById("divMessage").innerHTML ="<i>" + helloMessage + “</i>”.

где document  это объект по умолчанию в JavaScript, который позволяет манипулировать элементами в HTML коде вашей страницы.

Остальной код в quickstart.js занимается выполнением запроса к серверу, чтобы в ответ получить XMLсообщение. Функция createXmlHttpRequestObject() создает и возвращает экземпляр объекта XMLHttpRequest. Она несколько больше, чем могла бы быть, потому что нам необходимо сделать ее совместимой с различными типами броузеров, а пока основной интерес для нас представляет то, что она делает. Экземпляр XMLHttpRequest, ссылка на который хранится в переменной xmlHttp, используется функцией process() для передачи серверу асинхронных запросов.

Почему это так важно, чтобы обращения к серверу были асинхронными? Дело в том, что асинхронные запросы не приостанавливают работу пользователя (и, соответственно, ход его мыслей). Асинхронная обработка реализуется архитектурой, управляемой событиями, прекрасный пример  графический интерфейс с пользователем: если бы не было событий, вам наверняка пришлось бы постоянно проверять  не была ли нажата кнопка или не были ли изменены размеры окна. Благодаря наличию событий кнопка автоматически извещает приложение, когда по ней щелкают мышью, а вы можете предусмотреть выполнение необходимых действий в функции, обрабатывающей это событие. В AJAX такое положение вещей распространяется и на обращения к серверу  вы автоматически будете извещены, когда поступит ответ от сервера.

Если вам интересно узнать, как работают приложения, использующие синхронные запросы, измените третий аргумент функции xmlHttp.open, установив его в значение false, и после этого самостоятельно вызовите handleServerResponse, как это показано ниже. Запустив измененный таким образом пример, вы обнаружите, что поле ввода «замораживается» на время соединения с сервером (в данном случае длительность периода «замораживания» в значительной степени зависит от скорости соединения, поэтому задержка будет почти незаметной, если сервер запущен на той же самой машине).

Функция process() должна с помощью объекта XMLHttpRequest инициировать новый запрос. Однако это возможно только в том случае, если объект XMLHttpRequest не занят обработкой предыдущего запроса. Это может произойти, когда сервер занят обработкой нашего запроса более чем одну секунду. Это вполне возможно при достаточно медленном соединении с Интернетом. Таким образом, функция process() в первую очередь проверяет, может ли она инициировать новый запрос:

// выполнить асинхронный запрос HTTP с помощью объекта XMLHttpRequest
function processO
{
// работа возможна, только если обьект xmlHttp не занят
if (xmlHttp.readyState » 4 || xmlHttp.readyState == 0) {

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

// если соединение занято, повторить попытку через одну секунду
setTineout(“process()”, 1000);

Если линия свободна, можно послать новый запрос. Следующие строки подготавливают запрос к серверу, но не отправляют его:

// обратиться к сценарию quickstart.php на сервере
xmlHttp.open("GET", "quickstart.php?nane=" + папе, true);

Первый аргумент определяет метод передачи имени пользователя серверу. Здесь можно выбирать между методом GET и POST. Второй аргумент  имя страницы на сервере, к которой мы хотим обратиться. При использовании метода GET передаваемые параметры помещаются в строку запроса в виде пар имя/значение. Третий параметр должен иметь значение true, если вы хотите, чтобы запрос был произведен асинхронно. Когда выполняется асинхронный вызов, не надо ждать, пока поступит ответ. Вместо этого вы определяете функцию, которая будет вызвана автоматически при изменении состояния запроса:

// определить метод, который будет обрабатывать ответы сервера
xmlHttp.onreadystatechange = handleServerResponse;

Установив это свойство объекта, можете быть спокойны  функция handleServerResponse будет вызвана системой, как только чтолибо произойдет с вашим запросом. По окончании необходимых подготовительных операций запрос инициируется обращением к методу send объекта XMLHttpRequest:

// послать асинхронный запрос серверу xmlHttp.send(null);

функция handleServerResponse вызывается всякий раз, когда изменяется статус запроса. Но только значение 4 в свойстве xmlHttp. readyState говорит о том, что запрос сервера был выполнен и вы можете прочитать полученный ответ. Можно дополнительно проверить код завершения транзакции HTTP, который в случае успеха должен быть равен 200. Если все эти условия соблюдены, можно прочитать сообщение, полученное от сервера, и вывести его пользователю.

После того как ответ сервера будет прочитан и обработан, вызывается функция setTimeout, которая в свою очередь вызовет функцию process() через одну секунду, и весь процесс повторится (обратите внимание: совершенно необязательно, и AJAX не требует этого, чтобы на стороне клиента в цикле выполнялись повторяющиеся задачи).

// повторить последовательность действий
setTimeout(“process()”, 1000);

А теперь еще раз пройдемся по тем событиям, которые происходят после того, как пользователь загрузит страницу.

1. Пользователь загружает index.html

2. Пользователь начинает (или продолжает) ввод символов своего имени

3. Когда в quickstart. js запускается метод process(), он асинхронно обращается к сценарию quickstart.php, расположенному на стороне сервера. Текст, введенный пользователем, передается серверу в виде параметров в строке запроса (методом GET). Для обработки изменений состояния запроса предназначена функция handleServerResponse.

4. Сервер запускает сценарий quickstart.php. Он конструирует документ в формате XML, который включает в себя сообщение, передаваемое клиенту.

5. При каждом изменении состояния запроса на стороне клиента отрабатывает метод handleServerResponse. В последний раз он вызывается, когда ответ будет благополучно принят от сервера. Далее производится чтение документа XML (текст сообщения извлекается из него и отображается в странице).

6. Изображение перед пользователем постоянно обновляется с получением каждого нового сообщения от сервера, но он может продолжать ввод, не приостанавливаясь. Через одну секунду все повторится, начиная с пункта 2.


Партнеры сайта