Большинство веб-приложений используют модель запрос/ответ для получения полной HTML-страницы с сервера. Часто это повторяющийся процесс нажатия кнопки, ожидания ответа сервера, нажатия другой кнопки и последующего ожидания. С помощью Ajax и объекта XMLHttpRequest вы можете использовать модель запроса/ответа, которая не требует от пользователя ожидания ответа от сервера. В этой статье Бретт Маклафлин объясняет, как создавать экземпляры XMLHttpRequest, которые могут адаптироваться к различным браузерам, устанавливать и отправлять запросы, а также отвечать на сервер.
В предыдущей статье этой серии (ссылку см. в разделе «Ресурсы») мы представили приложения Ajax и рассмотрели основные концепции, лежащие в основе приложений Ajax. В основе этого лежит множество технологий, которые вы, вероятно, уже знаете: JavaScript, HTML и XHTML, немного динамического HTML и DOM (объектная модель документа). В этой статье мы сосредоточимся на одном моменте и сосредоточимся на конкретных деталях Ajax.
В этой статье вы познакомитесь с самыми основными и фундаментальными объектами и методами программирования, связанными с Ajax: объектом XMLHttpRequest. Этот объект на самом деле представляет собой просто общий поток, охватывающий все приложения Ajax, и, как и следовало ожидать, вам необходимо досконально понять этот объект, чтобы полностью реализовать свой программный потенциал. Фактически, иногда вы обнаружите, что для правильного использования XMLHttpRequest вы явно не можете использовать XMLHttpRequest. Что происходит?
Краткий обзор Web 2.0
Прежде чем углубиться в код, давайте взглянем на последние перспективы — важно очень четко понимать концепцию Web 2.0. Когда вы слышите термин «Web 2.0», вам следует сначала спросить: «Что такое Web 1.0?» Хотя люди редко упоминают Web 1.0, на самом деле это относится к традиционному Интернету с совершенно другой моделью запросов и ответов. Например, зайдите на сайт Amazon.com и нажмите кнопку или введите поисковый запрос. Запрос отправляется на сервер, а ответ возвращается в браузер. Запрос представляет собой не просто список книг и названий, а еще одну полноценную HTML-страницу. Поэтому вы можете увидеть мерцание или дрожание, когда веб-браузер перерисовывает страницу с новым HTML-кодом. Фактически, запросы и ответы четко видны на каждой новой странице, которую вы видите.
Web 2.0 (в значительной степени) устраняет это видимое двустороннее взаимодействие. Например, посетите такой сайт, как Google Maps или Flickr (ссылки на эти сайты с поддержкой Web 2.0 и Ajax см. в разделе «Ресурсы»). Например, на Картах Google вы можете перетаскивать карту для увеличения и уменьшения масштаба с минимальным перерисовыванием. Конечно еще есть запросы и ответы, но они скрыты за кадром. Для пользователя это более удобно и похоже на настольное приложение. Это новое ощущение и парадигма возникают, когда кто-то упоминает Web 2.0.
Задача состоит в том, чтобы сделать эти новые взаимодействия возможными. Очевидно, что вам по-прежнему необходимо отправлять запросы и получать ответы, но именно перерисовка HTML для каждого взаимодействия запрос/ответ создает ощущение медленного и неуклюжего веб-взаимодействия. Итак, очевидно, что нам нужен способ отправлять запросы и получать ответы, содержащие только необходимые данные, а не всю HTML-страницу. Единственный раз, когда вам нужно получить всю новую HTML-страницу, — это когда вы хотите, чтобы пользователь увидел новую страницу.
Но большинство взаимодействий добавляют детали к существующим страницам, изменяют основной текст или перезаписывают исходные данные. В этих случаях методы Ajax и Web 2.0 позволяют отправлять и получать данные без обновления всей HTML-страницы. Для тех, кто проводит много времени в Интернете, эта возможность может сделать ваши приложения более быстрыми и отзывчивыми, заставляя их время от времени возвращаться на ваш сайт.
Введение в XMLHttpRequest
Чтобы по-настоящему реализовать это великолепное чудо, вы должны быть хорошо знакомы с объектом JavaScript, а именно XMLHttpRequest. Этот маленький объект уже некоторое время присутствует в нескольких браузерах и лежит в основе Web 2.0, Ajax и многих других вещей, о которых я расскажу в этой колонке в течение следующих нескольких месяцев. Чтобы дать вам краткий обзор, вот лишь несколько методов и свойств, которые будут использоваться в этом объекте.
·open(): Установить новый запрос к серверу.
·send(): отправить запрос на сервер.
·abort(): Прервать текущий запрос.
·readyState: предоставляет состояние готовности текущего HTML.
·responseText: текст ответа на запрос, возвращаемый сервером.
Не волнуйтесь, если вы не знаете этих (или каких-либо из них), мы рассмотрим каждый метод и свойство в следующих нескольких статьях. Теперь вам следует знать, что именно делать с XMLHttpRequest. Обратите внимание, что эти методы и свойства связаны с отправкой запросов и обработкой ответов. Фактически, если вы посмотрите на все методы и свойства XMLHttpRequest, вы обнаружите, что все они относятся к очень простой модели запрос/ответ. Очевидно, что мы не столкнемся с каким-то особенно новым объектом графического пользовательского интерфейса или каким-то сверхзагадочным способом взаимодействия с пользователем, мы собираемся использовать очень простые запросы и очень простые ответы. Возможно, это звучит не так уж и много, но правильное использование этого объекта может произвести революцию в вашем приложении.
Простое новое
сначала требует создания новой переменной и присвоения ей экземпляра объекта XMLHttpRequest. Это так же просто, как использовать ключевое слово new в имени объекта в JavaScript, как показано в листинге 1.
Листинг 1. Создание нового объекта XMLHttpRequest
<script Language="javascript" type="text/javascript">
запрос вар = новый XMLHttpRequest();
</script>
Разве это не сложно? Помните, что JavaScript не требует указания типов переменных, поэтому вам не нужно делать то, что вы делаете в листинге 2 (что вы могли бы сделать в языке Java).
Листинг 2. Псевдокод Java для создания XMLHttpRequestXMLHttpRequest
request = new XMLHttpRequest()
Итак, в JavaScript вы создаете переменную с помощью var, даете ей имя (например, «запрос»), а затем назначаете ей новый экземпляр XMLHttpRequest; Затем объект можно использовать в функциях.
Обработка ошибок
На самом деле все может пойти не так, и приведенный выше код не обеспечивает никакой обработки ошибок. Лучший подход — создать объект и корректно выйти из него, если что-то пойдет не так. Например, любые старые браузеры (хотите верьте, хотите нет, но все еще есть люди, использующие старые версии Netscape Navigator) не поддерживают XMLHttpRequest, и вам нужно сообщить этим пользователям, что что-то не так. В листинге 3 показано, как создать этот объект для выдачи предупреждения JavaScript при возникновении проблемы.
Листинг 3. Создание XMLHttpRequest с возможностями обработки ошибок
<script Language="javascript" type="text/javascript">
вар запрос = ложь;
пытаться {
запрос = новый XMLHttpRequest();
} поймать (не удалось) {
запрос = ложь;
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
</script>
Обязательно усвойте следующие шаги:
1. Создайте новый запрос переменной и присвойте ему значение false. Позже в качестве условия оценки будет использоваться значение False, что означает, что объект XMLHttpRequest еще не создан.
2. Добавьте блок try/catch:
1) Попробуйте создать объект XMLHttpRequest.
2) Если это не удалось (catch (failed)), гарантируется, что значение запроса по-прежнему ложно.
3. Проверьте, является ли запрос по-прежнему ложным (он не будет ложным, если все в порядке).
4. При возникновении проблемы (ложный запрос) используйте предупреждение JavaScript, чтобы уведомить пользователя о возникновении проблемы.
Код очень прост, и большинству JavaScript и веб-разработчиков потребуется больше времени, чтобы по-настоящему понять его, чем прочитать и написать код. Теперь у вас есть фрагмент кода создания объекта XMLHttpRequest, который проверен на ошибки и может сказать вам, что пошло не так.
Кажется,с Microsoft
все в порядке, по крайней мере, пока вы не опробуете код в Internet Explorer. Если вы поэкспериментируете подобным образом, вы увидите плохую ситуацию, показанную на рисунке 1.
Рисунок 1. Ошибка отчета Internet Explorer
Что-то явно не так, и Internet Explorer вряд ли можно назвать устаревшим браузером, поскольку его используют 70% населения мира. Другими словами, если вы не поддерживаете Microsoft и Internet Explorer, вы не будете популярны в мире Интернета! Поэтому нам нужно применить другой подход к браузерам Microsoft.
Было проверено, что Microsoft поддерживает Ajax, но его версия XMLHttpRequest имеет другое имя. На самом деле, он называет это по-разному. Если вы используете более новые версии Internet Explorer, вам необходимо использовать объект Msxml2.XMLHTTP, а в более старых версиях Internet Explorer используется Microsoft.XMLHTTP. Нам необходимо поддерживать оба типа объектов (а также браузеры сторонних производителей). Взгляните на листинг 4, который основан на предыдущем коде и добавляет поддержку Microsoft.
Microsoft в этом участвует?
Много было написано о растущем интересе и участии Ajax и Microsoft в этой области. Фактически, говорят, что последняя версия Internet Explorer от Microsoft — версия 7.0, которая должна выйти во второй половине 2006 года — начнет напрямую поддерживать XMLHttpRequest, позволяя вам использовать новое ключевое слово вместо всего кода создания Msxml2.XMLHTTP. Но не стоит слишком волноваться: старые браузеры все еще нуждаются в поддержке, поэтому кроссбраузерный код не исчезнет в ближайшее время.
Листинг 4. Добавление поддержки браузеров Microsoft
<script Language="javascript" type="text/javascript">
вар запрос = ложь;
пытаться {
запрос = новый XMLHttpRequest();
} поймать (попробуймикрософт) {
пытаться {
запрос = новый ActiveXObject("Msxml2.XMLHTTP");
} поймать (другоеMicrosoft) {
пытаться {
запрос = новый ActiveXObject("Microsoft.XMLHTTP");
} поймать (не удалось) {
запрос = ложь;
}
}
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
</скрипт>
Из-за этих фигурных скобок легко запутаться, поэтому каждый шаг описан ниже:
1. Создайте новый запрос переменной и присвойте ему значение false. Используйте false в качестве условия оценки, что означает, что объект XMLHttpRequest еще не создан.
2. Добавьте блок try/catch:
1) Попробуйте создать объект XMLHttpRequest.
2) Если не получается (поймайте (trymicrosoft)):
1>Попробуйте использовать более новую версию браузера Microsoft для создания объекта, совместимого с Microsoft (Msxml2.XMLHTTP).
2> Если не удалось (catch (othermicrosoft)) попробуйте создать объект, совместимый с Microsoft (Microsoft.XMLHTTP), используя более старую версию браузера Microsoft.
2) Если это не удалось (catch (failed)), гарантируется, что значение запроса по-прежнему ложно.
3. Проверьте, является ли запрос по-прежнему ложным (он не будет ложным, если все пройдет хорошо).
4. Если возникает проблема (запрос ложный), используйте предупреждение JavaScript, чтобы уведомить пользователя о возникновении проблемы.
После изменения кода таким образом и тестирования его с помощью Internet Explorer вы должны увидеть созданную форму (без сообщения об ошибке). Результаты моего эксперимента показаны на рисунке 2.
Рисунок 2. Internet Explorer работает нормально
Статический и динамический
Взгляните еще раз на листинги 1, 3 и 4. Обратите внимание, что весь этот код вложен непосредственно в тег скрипта. Подобный код JavaScript, который не помещается в тело метода или функции, называется статическим JavaScript. Это означает, что код запускается за некоторое время до того, как страница отображается пользователю. (Хотя спецификация не знает с полной точностью, какой эффект этот код окажет на браузер при запуске, гарантируется, что он будет запущен до того, как пользователь сможет взаимодействовать со страницей.) Это также общий способ большинства Программисты Ajax создают объекты XMLHttpRequest.
Тем не менее, вы также можете поместить этот код в метод, подобный листингу 5.
Листинг 5. Перемещение кода создания XMLHttpRequest в метод
<script Language="javascript" type="text/javascript">
var
function createRequest() {
пытаться {
запрос = новый XMLHttpRequest();
} поймать (попробуймикрософт) {
пытаться {
запрос = новый ActiveXObject("Msxml2.XMLHTTP");
} поймать (другоеMicrosoft) {
пытаться {
запрос = новый ActiveXObject("Microsoft.XMLHTTP");
} поймать (не удалось) {
запрос = ложь;
}
}
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
}
</скрипт>
Если вы пишете свой код таким образом, вам необходимо вызвать этот метод перед обработкой Ajax. Поэтому также необходим код, подобный листингу 6.
Листинг 6. Создание метода с использованием XMLHttpRequest
<script Language="javascript" type="text/javascript">
var
function createRequest() {
пытаться {
запрос = новый XMLHttpRequest();
} поймать (попробуймикрософт) {
пытаться {
запрос = новый ActiveXObject("Msxml2.XMLHTTP");
} поймать (другоеMicrosoft) {
пытаться {
запрос = новый ActiveXObject("Microsoft.XMLHTTP");
} поймать (не удалось) {
запрос = ложь;
}
}
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
}
функция getCustomerInfo() {
создатьЗапрос();
// Делаем что-нибудь с переменной запроса
}
</скрипт>
Единственная проблема с этим кодом заключается в том, что он задерживает уведомление об ошибках, поэтому большинство Ajax-программистов не используют этот подход. Предположим, у вас есть сложная форма с 10 или 15 полями, полями выбора и т. д., и вы хотите активировать некоторый код Ajax, когда пользователь вводит текст в 14-е поле (сверху вниз в порядке формы). На этом этапе запуск getCustomerInfo() пытается создать объект XMLHttpRequest, но (в данном случае) терпит неудачу. Затем пользователю отображается предупреждение, ясно говорящее, что он не может использовать приложение. Но пользователи уже тратят много времени на ввод данных в формы! Это очень раздражает, и очевидно, что раздражающее поведение не заставит пользователей вернуться на ваш сайт.
Если вы используете статический JavaScript, пользователи очень быстро увидят сообщения об ошибках, когда нажмут на страницу. Это тоже раздражает, не так ли? Пользователь может ошибочно полагать, что ваше веб-приложение не может работать в его браузере. Но это, безусловно, лучше, чем тратить 10 минут на ввод информации, а потом увидеть ту же ошибку. Поэтому я рекомендую писать статический код, чтобы пользователи могли обнаружить проблемы как можно раньше.
Послеотправки запроса с помощью XMLHttpRequest
и получения объекта запроса вы можете войти в цикл запрос/ответ. Помните, что единственная цель XMLHttpRequest — предоставить вам возможность отправлять запросы и получать ответы. Все остальное — это работа JavaScript, CSS или другого кода на странице: изменение пользовательского интерфейса, переключение изображений, интерпретация данных, возвращаемых сервером. После подготовки XMLHttpRequest вы можете отправить запрос на сервер.
Добро пожаловать в «песочницу»
Ajax использует модель безопасности «песочницы». Поэтому Ajax-код (в частности, объект XMLHttpRequest) может отправлять запросы только в тот же домен, в котором он расположен. Мы расскажем больше о безопасности и Ajax в следующей статье, а пока просто знайте, что код, работающий на локальном компьютере, может отправлять запросы только к серверным сценариям на локальном компьютере. Если вы хотите, чтобы код Ajax запускался на www.breakneckpizza.com , запрос должен быть отправлен из сценария, работающего на www.breakneck.com .
Чтобы установить URL-адрес сервера,
необходимо сначала определить URL-адрес подключенного сервера. Это не является особым требованием для Ajax, но установить соединение все равно необходимо, и теперь вы, очевидно, должны знать, как построить URL. В большинстве приложений этот URL-адрес состоит из комбинации некоторых статических данных и данных из формы, которую обрабатывает пользователь. Например, код JavaScript в листинге 7 получает значение поля номера телефона и использует его для создания URL-адреса.
Листинг 7. Создание URL-адреса запроса
<script Language="javascript" type="text/javascript">
вар запрос = ложь;
пытаться {
запрос = новый XMLHttpRequest();
} поймать (попробуймикрософт) {
пытаться {
запрос = новый ActiveXObject("Msxml2.XMLHTTP");
} поймать (другоеMicrosoft) {
пытаться {
запрос = новый ActiveXObject("Microsoft.XMLHTTP");
} поймать (не удалось) {
запрос = ложь;
}
}
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
function getCustomerInfo() {
var телефон = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
}
</script>
Здесь нет ничего сложного для понимания. Сначала код создает новую переменную phone и присваивает ей значение поля формы с идентификатором «phone». В листинге 8 показан XHTML для этой формы, где вы можете увидеть поле телефона и его атрибут id.
Листинг 8. Форма пиццы Break Neck
<body>
<p><img src="breakneck-logo_4c.gif" alt="Пицца со сломанной шеей" /></p>
<форма действие="POST">
<p>Введите свой номер телефона:
<input type="text" size="14" name="phone" id="phone"
onChange="getCustomerInfo();" />
</p>
<p>Ваш заказ будет доставлен</p>
<div id="адрес"></div>
<p>Введите здесь свой заказ:</p>
<p><textarea name="order" rows="6" cols="50" id="order"></textarea></p>
<p><input type="submit" value="Заказать пиццу" id="submit" /></p>
</форма>
</body>
Также обратите внимание, что когда пользователь вводит номер телефона или меняет его, срабатывает метод getCustomerInfo(), показанный в листинге 8. Этот метод получает номер телефона и создает строку URL-адреса, хранящуюся в переменной url. Помните, что поскольку код Ajax изолирован в песочнице и может подключаться только к одному и тому же домену, фактически нет необходимости указывать доменное имя в URL-адресе. Сценарий в этом примере называется /cgi-local/lookupCustomer.php. Наконец, номер телефона добавляется к сценарию как параметр GET: "phone=" + escape(phone).
Если вы раньше не видели метод escape(), он используется для экранирования любых символов, которые невозможно правильно отправить в виде открытого текста. Например, пробелы в телефонных номерах будут преобразованы в символы %20, что позволит передавать эти символы в URL-адресе.
Вы можете добавить столько параметров, сколько необходимо. Например, если вам нужно добавить еще один параметр, просто добавьте его к URL-адресу и отделите символом амперсанда (&) [первый параметр отделяется от имени скрипта вопросительным знаком (?)].
Откройте запрос.
Когда у вас есть URL-адрес для подключения, вы можете настроить запрос. Это можно сделать с помощью метода open() объекта XMLHttpRequest. Этот метод имеет пять параметров:
request-type: тип отправляемого запроса. Типичные значения — GET или POST, но можно отправить и запрос HEAD.
url: URL-адрес для подключения.
asynch: true, если вы хотите использовать асинхронное соединение, в противном случае — false. Этот параметр является необязательным и по умолчанию имеет значение true.
имя пользователя: Если требуется аутентификация, вы можете указать здесь имя пользователя. Этот необязательный параметр не имеет значения по умолчанию. пароль: Если требуется аутентификация, вы можете указать здесь пароль. Этот необязательный параметр не имеет значения по умолчанию.
open() открывается?
Интернет-разработчики не пришли к единому мнению относительно того, что именно делает метод open(). Но на самом деле он не открывает запрос. Если вы отслеживаете сеть и передачу данных между страницей XHTML/Ajax и скриптом подключения, вы не увидите никакой связи при вызове метода open(). Непонятно, почему было выбрано это имя, но это явно не лучший выбор.
Обычно используются первые три параметра. Фактически, даже если требуется асинхронное соединение, третий параметр должен быть указан как «true». Это значение по умолчанию, но проще понять, настаивать на явном указании, является ли запрос асинхронным или синхронным.
Их объединение обычно приводит к строке кода, подобной той, что показана в листинге 9.
Листинг 9. Функция запроса открытия
getCustomerInfo() {
var телефон = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", URL, правда);
}
После того, как вы настроите URL-адрес, все остальное будет легко. Для большинства запросов достаточно GET (в следующей статье вы увидите, когда потребуется POST), плюс URL-адрес, и это все, что вам нужно для использования метода open().
Проблемы асинхронности
В следующей статье этой серии я потрачу много времени на написание и использование асинхронного кода, но вы должны понимать, почему последний параметр open() так важен. В общей модели запрос/ответ, такой как Web 1.0, клиент (браузер или код, работающий на локальном компьютере) отправляет запрос серверу. Запрос синхронный, то есть клиент ждет ответа от сервера. Когда клиент ждет, вы будете уведомлены об ожидании хотя бы в той или иной форме:
· Песочные часы (особенно в Windows).
·Вращающийся мяч (обычно на машинах Mac).
·Приложение в основном зависает, а затем через некоторое время курсор меняется.
Именно поэтому веб-приложения кажутся неуклюжими или медленными — из-за отсутствия настоящей интерактивности. При нажатии кнопки приложение фактически становится непригодным для использования до тех пор, пока не будет получен ответ на только что вызванный запрос. Если запрос требует большой обработки сервером, время ожидания может быть долгим (по крайней мере, в этом многопроцессорном мире, где DSL не требует ожидания).
Асинхронные запросы не ждут ответа от сервера. Приложение продолжает работу после отправки запроса. Пользователи по-прежнему могут вводить данные в веб-форму или даже выходить из формы. Здесь нет вращающихся шариков или песочных часов, приложение заметно не зависает. Сервер спокойно отвечает на запрос и, когда он выполнен, сообщает первоначальному запрашивающему, что задание завершено (вы увидите, как скоро). В результате приложение становится менее медленным и медленным, более отзывчивым, интерактивным и работает намного быстрее. Это всего лишь одна часть Web 2.0, но это важная часть. Все старые компоненты графического пользовательского интерфейса и парадигмы веб-дизайна не могут преодолеть медленную синхронную модель запроса/ответа.
Отправка запросов
После настройки open() вы можете отправлять запросы. К счастью, метод отправки запросов имеет более подходящее имя, чем open(): это send().
send() имеет только один параметр — отправляемый контент. Но прежде чем рассматривать этот метод, напомните, что вы уже отправили данные через сам URL-адрес:
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
Хотя для отправки данных вы можете использовать send(); , Но можно также отправлять данные через сам URL-адрес. Фактически, с помощью GET-запросов (которые встречаются примерно в 80% типичных Ajax-приложений) гораздо проще отправлять данные с помощью URL-адреса. Если вам необходимо отправить защищенную информацию или XML, вы можете рассмотреть возможность использования send() для отправки содержимого (защищенные данные и сообщения XML будут обсуждаться в последующих статьях этой серии). Если вам не нужно передавать данные через send(), просто передайте значение null в качестве параметра этого метода. Итак, в примерах этой статьи вы обнаружите, что это все, что вам нужно сделать (см. листинг 10).
Листинг 10.
Функция запроса на отправку getCustomerInfo() {
var телефон = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", URL, правда);
запрос.отправить (ноль);
}
Укажите метод обратного вызова
В том, что мы делаем сейчас, очень мало нового, революционного или асинхронного. Следует признать, что маленькое ключевое слово «true» в методе open() устанавливает асинхронный запрос. Но в остальном код ничем не отличается от программирования с использованием сервлетов Java и JSP, PHP или Perl. Так в чем же самый большой секрет Ajax и Web 2.0? Секрет заключается в простом свойстве onreadystatechange XMLHttpRequest.
Сначала обязательно поймите порядок действий в этом коде (при необходимости просмотрите листинг 10). Создайте его запрос, а затем сделайте запрос. Кроме того, поскольку запрос является асинхронным, метод JavaScript (getCustomerInfo() в примере) не ждет сервера. Таким образом, код продолжит выполнение, то есть метод закроется и управление вернется в форму. Пользователь может продолжать вводить информацию, а приложение не ждет сервера.
Возникает интересный вопрос: что происходит после того, как сервер завершает запрос? Ответ в том, что ничего не происходит, по крайней мере для текущего кода! Очевидно, это не сработает, поэтому серверу нужны какие-то инструкции о том, что делать после завершения обработки запроса, отправленного ему через XMLHttpRequest.
Справочные функции в JavaScript:
JavaScript — слабо типизированный язык, и вы можете использовать переменные для ссылки на что угодно. Поэтому, если вы объявляете функцию updatePage(), JavaScript также обрабатывает имя функции как переменную. Другими словами, вы можете ссылаться на функцию в своем коде, используя имя переменной updatePage.
Листинг 11. Установка метода обратного вызова
function getCustomerInfo() {
var телефон = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", URL, правда);
request.onreadystatechange = updatePage;
запрос.отправить (ноль);
}
Важно отметить, где в коде установлено это свойство — оно устанавливается перед вызовом send(). Это свойство необходимо установить перед отправкой запроса, чтобы сервер мог просмотреть его после ответа на завершенный запрос. Теперь осталось написать метод updatePage(), которому посвящен последний раздел этой статьи.
Сервер обработки отвечает
на запрос, пользователь с удовольствием использует веб-форму (пока сервер обрабатывает запрос), и теперь сервер завершил обработку запроса. Сервер просматривает атрибут onreadystatechange, чтобы определить, какой метод вызывать. В противном случае относитесь к своему приложению как к любому другому приложению, независимо от того, является ли оно асинхронным или нет. Другими словами, вам не обязательно предпринимать специальные действия для написания метода, отвечающего серверу, вам просто нужно изменить форму, позволить пользователю посетить другой URL-адрес или сделать все, что нужно серверу ответа. В этом разделе мы сосредоточимся на ответах сервера и типичном действии — мгновенном изменении части формы, которую видит пользователь.
Обратные вызовы и Ajax
Теперь мы увидели, как сообщить серверу, что делать после завершения: установить для свойства onreadystatechange объекта XMLHttpRequest имя функции, которую нужно запустить. Таким образом, функция будет вызываться автоматически после того, как сервер обработает запрос. Также нет необходимости беспокоиться о каких-либо параметрах функции. Начнем с простого метода, показанного в листинге 12.
Листинг 12. Код метода обратного вызова
<script Language="javascript" type="text/javascript">
вар запрос = ложь;
пытаться {
запрос = новый XMLHttpRequest();
} поймать (попробуймикрософт) {
пытаться {
запрос = новый ActiveXObject("Msxml2.XMLHTTP");
} поймать (другоеMicrosoft) {
пытаться {
запрос = новый ActiveXObject("Microsoft.XMLHTTP");
} поймать (не удалось) {
запрос = ложь;
}
}
}
если (!запрос)
alert("Ошибка инициализации XMLHttpRequest!");
function getCustomerInfo() {
var телефон = document.getElementById("phone").value;
var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);
request.open("GET", URL, правда);
request.onreadystatechange = updatePage;
запрос.отправить (ноль);
}
функция updatePage() {
alert("Сервер готов!");
}
</script>
Он просто выдает несколько простых предупреждений, сообщающих вам, когда сервер завершил свою задачу. Попробуйте использовать этот код на своей веб-странице и откройте его в браузере (если вы хотите увидеть XHTML в этом примере, см. листинг 8). Введите номер телефона и затем покиньте поле, вы увидите всплывающее окно с предупреждением (как показано на рисунке 3), но нажмите ОК и оно появится снова...
Рисунок 3. Ajax-код для всплывающего предупреждения
В зависимости от браузера вы можете увидеть два, три или даже четыре предупреждения, прежде чем форма перестанет появляться. Что происходит? Оказывается, мы не учли состояние готовности HTTP, которое является важной частью цикла запрос/ответ.
Состояние готовности HTTP
Как упоминалось ранее, сервер ищет метод, который будет вызван в атрибуте onreadystatechange XMLHttpRequest после завершения запроса. Это правда, но неполная. Фактически, он вызывает этот метод каждый раз, когда меняется статус готовности HTTP. Что это значит? Сначала вы должны понять состояние готовности HTTP.
Статус готовности HTTP представляет собой статус или состояние запроса. Он используется для определения того, был ли запрос запущен, получен ли ответ или модель запроса/ответа завершена. Это также может помочь определить, безопасно ли читать текст ответа или данные, предоставленные сервером. В приложениях Ajax необходимо учитывать пять состояний готовности:
·0: запрос не был отправлен (до вызова open()).
·1: запрос установлен, но еще не отправлен (до вызова send()).
·2: Запрос отправлен и обрабатывается (заголовок содержимого обычно можно получить из ответа).
·3: Запрос обработан, и некоторые данные обычно доступны в ответе, но сервер не завершил ответ.
·4: Ответ завершен, и вы можете получить доступ к ответу сервера и использовать его.
Как и в случае с большинством кроссбраузерных проблем, эти состояния готовности не используются последовательно. Вы могли бы ожидать, что статус готовности задачи изменится с 0 на 1, на 2, на 3, на 4, но это случается редко. Некоторые браузеры никогда не сообщают 0 или 1, а начинают сразу с 2, затем 3 и 4. Другие браузеры сообщают обо всех статусах. Другие сообщают о статусе готовности 1 несколько раз. Как видно из предыдущего раздела, сервер вызывает updatePage() несколько раз, и при каждом вызове появляется окно с предупреждением — оно может отличаться от ожидаемого!
Для программирования Ajax единственное состояние, которое необходимо обрабатывать напрямую, — это состояние готовности 4, которое указывает, что ответ сервера завершен и данные ответа можно безопасно использовать. Исходя из этого, первая строка метода обратного вызова должна выглядеть как в листинге 13.
Листинг 13. Проверка готовности
функции updatePage() {
если (request.readyState == 4)
alert("Сервер готов!");
}
После внесения изменений вы можете убедиться, что обработка сервером завершена. Попробуйте запустить новую версию кода Ajax, и теперь вы увидите предупреждающее сообщение, отображаемое только один раз, как и ожидалось.
Коды состояния HTTP
Хотя код в листинге 13 выглядит нормально, есть проблема: что, если сервер ответит на запрос и завершит обработку, но сообщит об ошибке? Имейте в виду, что серверный код должен понимать, что он вызывается Ajax, JSP, простыми HTML-формами или другими типами кода, но может сообщать информацию только с использованием традиционных веб-методов. В мире Интернета HTTP-код может решать различные проблемы, которые могут возникнуть в запросе.
Например, вы наверняка сталкивались с ситуацией, когда вы ввели неправильный URL-запрос и получили код ошибки 404, что означает, что страница не существует. Это лишь один из многих кодов ошибок, которые можно получить с помощью HTTP-запроса (полный список кодов состояния см. по ссылке в разделе «Ресурсы»). Также распространены номера 403 и 401, которые указывают, что данные, к которым осуществляется доступ, защищены или запрещены. В любом случае эти коды ошибок получаются из завершенного ответа. Другими словами, сервер выполнил запрос (то есть статус готовности HTTP равен 4), но не вернул данные, которые ожидал клиент.
Поэтому помимо статуса готовности вам также необходимо проверить статус HTTP. Ожидаемый код состояния — 200, что означает, что все прошло хорошо. Если статус готовности равен 4, а код состояния — 200, вы можете обрабатывать данные сервера, и данные должны быть запрошенными данными (а не ошибками или другой проблемной информацией). Поэтому нам также необходимо добавить проверку статуса в метод обратного вызова, как показано в листинге 14.
Листинг 14. Проверка кода состояния HTTP
function updatePage() {
если (request.readyState == 4)
если (запрос.статус == 200)
alert("Сервер готов!");
}
Чтобы добавить более надежную обработку ошибок и попытаться избежать чрезмерного усложнения путем добавления одной или двух проверок кода состояния, взгляните на модифицированную версию updatePage() в листинге 15.
Листинг 15. Добавьте небольшую
функцию проверки ошибок updatePage() {
если (request.readyState == 4)
если (запрос.статус == 200)
alert("Сервер готов!");
иначе, если (request.status == 404)
alert("URL-адрес запроса не существует");
еще
alert("Ошибка: код статуса " + request.status);
}
Теперь измените URL-адрес в getCustomerInfo() на несуществующий URL-адрес и посмотрите, что произойдет. Вы должны увидеть предупреждающее сообщение о том, что запрошенный URL-адрес не существует — отлично! Трудно обрабатывать все условия ошибки, но это небольшое изменение может охватить 80% проблем в типичном веб -приложении.
Чтение текста ответа
теперь гарантирует, что запрос был обработан (через статус готового), сервер дал нормальный ответ (через код состояния), и, наконец, мы можем обработать данные, возвращаемые сервером. Возвращенные данные хранятся в свойстве ответа объекта xmlhttprequest.
Содержание текста в ответете, например, формат и длина, намеренно остается расплывчатым. Таким образом, сервер может установить текст на все. Например, один сценарий может вернуть значения, разделенные запятыми, другой использует трубу (символ | символ) для разделения значений, а другой возвращает длинную текстовую строку. Сервер должен решить, куда идти.
В примере, используемом в этой статье, сервер возвращает последний заказ клиента и адрес клиента, разделенный символом трубы. Порядок и адрес затем используются для установки значений элементов в форме.
Листинг 16. Обработка
функции ответа сервера UpdatePage () {
if (request.readystate == 4) {
if (request.status == 200) {
var response = request.responsetext.split ("|");
document.getElementbyId ("order"). value = response [0];
document.getElementById ("адрес"). innerHtml =
ответ [1] .Replace (/ n/g, "");
} еще
Alert («Статус IS» + request.status);
}
}
Во -первых, получите ответный ответ и разделите его от трубы, используя метод JavaScript split (). Полученный массив помещается в ответ. Первое значение в массиве - предыдущий заказ - доступ к ответу [0] и устанавливается на значение поля с идентификатором «Порядок». Второй ответ значения [1], адрес клиента, требует немного большей обработки. Поскольку строки в адресе разделены обычными сепараторами линии (« n» символов), код должен использовать сепараторы линий в стиле XHTML <Br />. Процесс замены выполняется с использованием функции reply () и регулярных выражений. Наконец, модифицированный текст используется как внутренний HTML в HTML -форме Div. Результатом является то, что форма внезапно обновляется с информацией о клиенте, как показано на рисунке 4.
Рисунок 4. Форма разрыва шеи после получения данных клиента
Прежде чем закончить эту статью, я хотел бы представить еще один важный атрибут Xmlhttprequest, responsexml. Это свойство содержит (как вы, возможно, догадались) ответ XML, если сервер решит использовать ответ XML. Обработка ответов XML сильно отличается от обработки обычного текста, включающего анализ, модель объекта документа (DOM) и другие проблемы. XML будет рассмотрен дальше в более поздней статье. Но так как responsexml обычно обсуждается вместе с ответом, он заслуживает упоминания здесь. Для многих простых приложений Ajax ApportExt будет достаточно, но вскоре вы увидите, что XML также можно хорошо обрабатывать приложения AJAX.
Вывод,
вы можете немного устать от Xmlhttprequest. Но вы используете этот объект снова и снова на каждой странице и приложении, которое вы пишете с помощью AJAX. Честно говоря, есть кое -что сказать для Xmlhttprequest. В следующей статье будет представлена то, как использовать Post и получить запросы, чтобы установить заголовки контента в запросах и прочитать заголовки контента из ответов на сервера, а также пойму, как кодировать запросы и обработать XML в модели запроса/ответа.
Позже мы представим общие наборы инструментов Ajax. Эти наборы инструментов фактически скрывают многие детали, описанные в этой статье, что облегчает программирование AJAX. Вы можете задаться вопросом, почему вам нужно кодировать детали низкого уровня, когда существует так много инструментов. Ответ заключается в том, что в приложении трудно определить проблемы, не зная, что делает приложение.
Поэтому не игнорируйте детали и не просто просмотрите, и если что -то пойдет не так с этим удобным и великолепным инструментом, вам не придется поцарапать голову или отправлять электронное письмо на поддержку. Если вы понимаете, как использовать Xmlhttprequest напрямую, вам будет легко отлаживать и решить самые странные проблемы. Ящик для инструментов хорош только в том случае, если вы позволите ему решить ваши проблемы.
Поэтому, пожалуйста, ознакомьтесь с Xmlhttprequest. На самом деле, если у вас есть код AJAX, который использует набор инструментов, попробуйте переписать его, используя объект Xmlhttprequest и его свойства и методы. Это хорошее упражнение, чтобы помочь вам лучше понять принципы.
В следующей статье будет обсуждаться этот объект дальше, исследуя некоторые из его более интересных свойств (таких как recsomexml), и как использовать запросы Post и отправлять данные в разных форматах. Пожалуйста, начните писать код, и мы обсудим его снова через месяц.