ЛАБОРАТОРНАЯ РАБОТА № 18 (9 JavaScript)
Тема: Технология AJAX
Цель:
Изучение особенностей технологии AJAX для получения данных с сервера
ОГЛАВЛЕНИЕ
1 Технология AJAX
1.1 Особенности технологии AJAX
1.2 Использование объекта XMLHttpRequest
1.2.1 Создание объекта xmlHttp
1.2.2 Формирование запроса к серверу
1.2.3 Получение данных из сервера
Пример 1
Пример 2
Индивидуальные задания
1 Технология AJAX
1.1 Особенности технологии AJAX
AJAX (Asynchronous JavaScript And XML - асинхронный JavaScript и XML)
представляет собой технологию, позволяющую при необходимости в фоновом режиме
(не прерывая работы пользователя и незаметно для него) выполнять запросы к
серверу и получать дополнительные данные для обновления отдельных частей
Web-страницы, тем самым исключая необходимость повторной загрузки страницы.
Например, выполнять на стороне сервера проверку правильности заполнения данных
пользоваетелем по мере их ввода.
Без использования технологии AJAX для решения этой
задачи имеются такие возможности:
- выполнять проверку на стороне сервера, но в этом случае необходимо
формировать новую Web-страниц, что увеличивает загрузку сети и увеличивает
время ожидания клиента;
- выполнять проверку на стороне клиенте, но при этом зачастую необходимо
хранить большой объем информации на компьютере клиента.
Для применения AJAX необходимы следующие компоненты:
- JavaScript (основной компонент);
- объект XMLHttpRequest;
- серверные технологии (например, PHP).
Первоначально технологию AJAX разработала фирма Microsoft как объект ActiveX
для браузера Internet Explorer. Затем фирма Mozilla создала объект
XMLHttpRequest с (почти) идентичными API, который в настоящее время
поддерживается всеми современными браузерами.
Рекомендации организации W3C аналогичной
функциональности пока не применены ни в одном браузере.
1.2 Использование объекта XMLHttpRequest
Объект XMLHttpRequest дает возможность отправлять
асинхронные HTTP-запросы из кода JavaScript серверу, принимать от него ответы и
обновлять отдельные части Web-страницы, не прерывая работу пользователя. Имеет
следующие методы и свойства:
- abort() - останавливает выполнение текущего запроса;
- getAllResponseHeaders() - возвращает все HTTP-заголовки ответа в виде
строки;
- getResponseHeader(header) - возвращает указанный HTTP-заголовок ответа в
виде строки;
- open(method, URL [, async_flag [, userName [. password ]]]) -
инициализирует параметры запроса, где:
- method - один из методов обмена данными с сервером: наиболее часто
используются GET и POST, но разрешены также методы HEAD, PUT или DELETE;
- URL - абсолютный или относительный URL-адрес сервера;
- async_flag (необязательнлый параметр) - значение true означает асинхронный режим работы с сервером:
скрипт, послав запрос серверу, продолжает свою работу (значение по умолчанию),
значение false означает синхронный режим работы с сервером: скрипт, послав
запрос серверу, приостанавливает свою работу, ожидая ответа от сервера;
- userName (необязательнлый параметр) - имя пользователя для аутентификации,
если параметр равен Null или "" и сайт требует аутентификации, то появляется
окно login;
- password (необязательнлый параметр) - пароль пользователя для
аутентификации, если равен Null или "", то игнорируется;
- send(data) - выполняет запрос, данные указываются только для методов POST
или PUT;
- setRequestHeader(level, value) - указывает имя и значение HTTP-заголовка в
запросе;
- onreadystatechange - используется для установки функции обратного вызова,
которая будет обслуживать изменения состояния запроса;
- readyState - возвращает состояние запроса:
- 0 - не инициализирован;
- 1 - выполняется подготовка запроса;
- 2 - запрос отправлен;
- 3 - выполняется обмен;
- 4 - обмен завершен.
- responseText - возвращает ответ сервера в виде строки;
- responseXML - возвращает ответ сервера в формате XML;
- responseStream - возвращает ответ сервера в виде двоичных данных;
- status - возвращает HTTP-код состояния запроса;
- statusText - возвращает сообщение о состоянии запроса.
Использование методов и свойств объекта XMLHttpRequest
приведено в примере № 1, в котором
выполняется получение текстовых данных из локального сервера, и в примере
№ 2, в котором выполняется
получение случайных чисел из удаленного сервера. В этих примерах осуществляется:
- создание объекта xmlHttp;
- формирование запроса к серверу;
- получение данных из сервера.
1.2.1 Создание объекта xmlHttp
Создание объекта xmlHttp осуществляется с помощью
функции createxmlHttp().
Поскольку объект xmlHttp создается в обоих примерах
(№ 1 и
№ 2), оператор присвоения,
вызывающий функцию createxmlHttp() и сама функция
описаны во внешнем файле ajax.js:
xmlHttp=createxmlHttp();
function createxmlHttp()
{
try
{
var xmlHttp=new XMLHttpRequest(); //var делает переменную локальльной
}
catch(e)
{
xmlHttp=new ActiveXObject("Microsoft.XMLHttp");
}
if(!xmlHttp) alert("Объект xmlHttp не создан");
else return xmlHttp;
}
Функция createxmlHttp() содержит конструкцию
try/catch, которая используется для проверки того,
выполняется ли некоторый код JavaScpipt без ошибок:
try
{
// Проверяемый код
}
catch(e)
{
// Обработка ошибки
}
Проверяемый код помещается в блок try{}. Если при
выполнении кода произошла ошибка (возникла исключительная ситуация), то
управление передается блоку catch(e){}, который
перехватывает возникшее исключение и обрабатывает ошибку. При этом исключение
не доходит до интерпретатора JavaScpipt и поэтому не сообщается пользователю.
Если в блоке try{} код выполняется без ошибок, то
блок catch(e){} управление не получает вовсе.
Как отмечалось выше, современные браузеры
поддерживают работу с XMLHttpRequest. Однако это не
относится к браузерам IE версии 6 и ниже. Поэтому функция
createxnlHttp() сначала пытается создать объект
xmlHttp с помощью класса
XMLHttpRequest (блок try{}).
Если при этом возникает исключительлная ситуация, управление передается в блок
catch(e){}, где делается попытка создать объект
xmlHttp уже с помощью объекта
ActiveXObject.
Если объект и при этом создать не удается, то
выводится сообщение о том, что объект xmlHttp не
создан.
1.2.2 Формирование запроса к серверу
После создания объекта xmlHttp можно использовать
его методы и свойства для организации запроса к серверу. Это делается с помощью
функции process(), которая как и функция
createxnlHttp() используется в примерах
№ 1 и
№ 2 и хранится в файле
ajax.js:
function process()
{
if(xmlHttp)
{
try
{
xmlHttp.open("GET",serverAddr+serverPar,true);
xmlHttp.onreadystatechange=handleStateChange;
xmlHttp.send(null);
}
catch(e)
{
alert("Невозможно соединится с сервером:\n"+e.toString()+
"\n"+e.description);
}
}
}
Функция process() сначала проверяет, создан ли
объект xmlHttp. Если создан, то выполняются следующие
действия:
- С помощью метода open() задаются значения
параметров соединения с сервером:
- метод - GET;
- адрес сервера и передаваемые параметры указываются с помощью переменных
serverAddr и serverPar;
- режим обмена - асинхронный.
- С помощью свойства onreadystatechange указывается
обработчик изменений состояния запроса - функция handleStateChange;
- С помощью метода send() посылается запрос на сервер;
- С помощью конструкции try{}/catch(e){} проверяется, не возникла ли ошибка
при выполнении вышеописанных действий по созданию и отправлению запроса на
сервер.
При возникновении исключительной ситуации на экран выводится сообщение
о невозможности соединения с сервером, к которому добавляется перехваченное
сообщение e, преобразованное в строку.
Имеется две возможности преобразования
e:
- с помощью метода toString();
- с помощью свойства description.
Функция process() использует обе эти возможности.
При этом в случае, например, неправильного задания URL-адреса сервера на экране появляются
следующие сообщения:
Невозможно соединится с сервером
[object Error]
Отказано в доступе
1.2.3 Получение данных из сервера
Получение данных из сервера выполняется по разному в примере
№ 1 и в примере
№ 2, поэтому будет рассмотрено
отдельно.
Пример 1
<HTML>
<HEAD>
<TITLE>Чтение текста из сервера с помощью AJAX</TITLE>
<SCRIPT SRC="ajax.js"></SCRIPT>
<SCRIPT>
serverAddr="http://zykov/data.txt";
serverPar="";
function handleStateChange()
{
myDiv=document.getElementById("div");
if(xmlHttp.readyState==1)
{
myDiv.innerHTML+="Состояние запроса:1 (подготовка к отправлению)";
try { myDiv.innerHTML+=", статус: "+xmlHttp.statusText+"<BR/>"; }
catch(e) { myDiv.innerHTML+="<BR/>"; }
}
else
{
if(xmlHttp.readyState==2)
{
myDiv.innerHTML+="Состояние запроса:2 (отправлен)";
try { myDiv.innerHTML+=", статус: "+xmlHttp.statusText+"<BR/>"; }
catch(e) { myDiv.innerHTML+="<BR/>"; }
}
else
{
if(xmlHttp.readyState==3)
{
myDiv.innerHTML+="Состояние запроса:3 (идет обмен)";
try { myDiv.innerHTML+=", статус: "+xmlHttp.statusText+"<BR/>"; }
catch(e) { myDiv.innerHTML+="<BR/>"; }
}
else
{
if(xmlHttp.readyState==4)
{
myDiv.innerHTML+="Состояние запроса:4 (обмен завершен)";
try { myDiv.innerHTML+=", статус: "+xmlHttp.statusText+"<BR/>"; }
catch(e) { myDiv.innerHTML+="<BR/>"; }
if(xmlHttp.status==200)
{
try
{
resp=xmlHttp.responseText;
myDiv.innerHTML+="<P>Сервер передал:"+resp;
}
catch(e) { alert("Ошибка чтения ответа: "+e.description); }
}
else { alert("Ошибка получения данных\n статус: "+xmlHttp.statusText);}
}
}
}
}
}
</SCRIPT>
</HEAD>
<BODY onLoad="process()">
<DIV ID="div" />
</BODY>
</HTML>
В примере 1 осуществляется чтение текстовых данных с локального сервера с
помощью технологии AJAX: в переменную
serverAddr заносится URL-адрес файла
локального сервера ("http://zykov/data.txt"), который содержит строку "Привет,
клиент!", а в переменную serverPar - пустая строка, поскольку в этом примере
данные на сервер не передаются.
Поскольку технология AJAX
требует использования Web-сервера, он должен быть запущен до выполнения примера.
Необходимо также отметить, что текстовые данные, если
они являются кириллицей, должны быть сохранены на сервере в кодировке UTF-8.
Фукция handleStateChange()
с помощью свойства readyState проверяет
текущее состояние запроса и при его изменении выводит на экран в тэг <DIV>
с помощью свойства innerHTML такие данные: номер
состояния, его текстовое значение и статус. Текстовое значение статуса
определяется с помощью свойства statusText объекта
xmlHttp. Поскольку не для всех состояний запроса оно
доступно, применяется конструкция try/catch(e).
Вывод всех состояний запроса сделан с учебной
целью. Для получения данных достаточно проанализировать состояние 4 ("обемен
данными завершен"), что и сделано в примере
№ 2.
Затем в состоянии 4 с помощью свойства
status определяется, нормально ли закончился обмен
данными с сервером. Если статус равен 200 (текстовое значение "OK"), что
означает, что операции с сервером закончились успешно, делается попытка чтение
данных, возвращенных сервером. Если ошибки нет - данные выводятся на экран, в
виде свойства innerText тэга <DIV>.
В случае возникновения ошибки на экран выводится
сообщение "Ошибка чтения ответа" с указанием дополнительных данных с помощью
свойства e.description.
Если сервер передает другое значение статуса, что
означает, что обмен произошел с ошибками, на экран выводится соответствующее
сообщение с указанием статуса ошибки в текстовом виде.
При выполнении всех операций в примере 1 без
ошибок на экран будут выведены следующие данные:
Состояние запроса:1 (подготовка к отправлению)
Состояние запроса:2 (отправлен), статус: OK
Состояние запроса:3 (идет обмен), статус: OK
Состояние запроса:4 (обмен завершен), статус: OK
Сервер передал: Привет, клиент!
Если необходимо осуществить чтение данных, находящихся на сервере в
формате XML, например, из файла data.xml содержащего такие данные:
<?xml version="1.0" ?>
<name>Robert Sheckly</name>,
необходимо, помимо указания нового адреса файла -
serverAddr="http://zykov/data.xml", заменить в
функции handleStateChange() строку
resp=xmlHttp.responseText;
строкой
resp=xmlHttp.responseXML.getElementsByTagName("name")[0].firstChild.data;
Тогда вместо сообщения
Сервер передал: Привет, клиент!
появится сообщение
Сервер передал: Robert Sheckly
Пример 2
<HTML>
<HEAD>
<TITLE>Чтение случайных чисел из удаленного сервера с помощью AJAX/TITLE>
<SCRIPT>
serverAddr="http://www.random.org/integers/";
serverPar="?num=1&min=1&max=25&col=1&base=10&format=plain";
function handleStateChange()
{
myDiv=document.getElementById("div");
if(xmlHttp.readyState==4)
{
if(xmlHttp.status==200)
{
try { myDiv.innerHTML+=xmlHttp.responseText; }
catch(e) { alert("Ошибка чтения ответа: "+e.toStrintg()); }
}
else { alert("Ошибка получения данных\n статус: "+xmlHttp.statusText);}
}
}
</SCRIPT>
<SCRIPT SRC="ajax.js"></SCRIPT>
</HEAD>
<BODY onLoad="process()">
<DIV ID="div" />
</BODY>
</HTML>
В примере 2 осуществляется получение случайных чисел с удаленного сервера с
помощью технологии AJAX: в переменную
serverAddr заносится URL-адрес удаленного сервера
("http://www.random.org/integers/"), который снабжает клиентов настоящими
случайными числами, а в переменную serverPar - строку
"?num=1&min=1&max=20&col=1&base=10&format=plain", задающую значения следующих
параметров запроса на получение случайных чисел:
- num - количество получаемых чисел;
- min - минимальное число диапазона;
- max - максимальное число диапазона;
- col - количество столбцов для вывода случайных чисел на экран;
- base - основание системы счисления случайных чисел;
- format - формат представления случайных чисел:
- plain - в виде простого текста;
- html - в виде HTML-документа.
В отличии от примера № 1
функция handleStateChange() не содержит кода,
осуществляющего вывод на экран названия и статус различных состояний запроса.
В результате работы скрипта при каждом запросе на
экран выводится одно случайное число в диапазоне от 1 до 25.
Индивидуальные задания
Отметить указанный в таблице объект и осуществить из заданной точки его движение
с заданной функцией по указанному событию.
№ | Объект | (X,Y) | Фукция F(x) | Куда | Отметка | Движение
|
---|
1 | Слово | X=0;Y=450 | 2x+5 | Вправо/вверх | onDblclick | onKeydown/Alt-1
|
2 | Рисунок | X=300;Y=400 | 25cos(x) | Вверх | onClick | onDblclick
|
3 | Ссылка | X=450;Y=220 | 40sin(3x) | Влево | onMouseover | onKeydown/ShiftLeft
|
4 | Таблица | X=600;Y=400 | x*x/500 | Влево/вверх | onMousemove> | onKeydown/Shift-Z
|
5 | Буква | X=200;Y=0 | exp(x/100) | Вниз | onContextmenu | onKeydown/Ctrl-5
|
6 | Рисунок | X=10;Y=300 | 30log(x+10) | Вправо | onClick | onContextmenu
|
7 | Ссылка | X=600;Y=200 | 10tan(x) | Влево | onDblclick | onKeydown/Tab-2
|
8 | Слово | X=50;Y=50 | 0.001x*x+x | Вправо/вниз | onMousemove | onKeydown/W
|
9 | Кнопка | X=500;Y=5 | 60sin(x*x) | Влево/вниз | onContextmenu | onClick |
|
10 | Буква | X=250;Y=450 | 25cos(2x+1) | Вверх | onClick | onContextmenu
|
11 | Кнопка | X=350;Y=0 | 0.5exp(x/250) | Вниз | onDblclick | onKeydown/1
|
12 | Ссылка | X=75;Y=175 | 50log(x+5)-50 | Вправо | onMousemove | onContextmenu
|
13 | Таблица | X=20;Y=420 | 0.2x+45 | Вправо/вверх | onMousemover | onKeydown/Atd>
|