Освоение Ajax: Часть 3. Усовершенствованные запросы и ответы в Ajax

В совершенстве изучите коды состояния HTTP, состояния готовности и объект XMLHttpRequest

Для многих Web-разработчиков выполнение простых запросов и получение простых ответов – это все, что когда-нибудь может им понадобиться, но для разработчиков, которые хотят освоить Ajax, необходимо полное понимание кодов состояния HTTP, состояний готовности и объекта XMLHttpRequest. В этой статье Брэт Маклафлин расскажет о различных кодах состояния и продемонстрирует, как браузеры их воспринимают. Он расскажет также о малоиспользуемых HTTP-запросах, которые вы можете применять с Ajax.

Бретт Маклафлин (Brett McLaughlin), Автор/Редактор, O'Reilly and Associates

Бретт Маклафлин (Brett McLaughlin) работает с компьютерами со времен Logo (помните маленький треугольник?) с такими компаниями как, например, asNextel Communications и Lutris Technologies. В последние годы он стал одним из очень известных авторов и программистов в сообществе Java и XML. Его последняя книга "Java1.5 Tiger: Заметки разработчика", являющаяся первой доступной книгой по новой версии Java, и его классическая "Java и XML" остаются одними из определяющих работ по использованию XML-технологий в Java.



14.02.2006

В последней статье этой серии я предоставил введение в объект XMLHttpRequest, центральный элемент Ajax-приложения, который управляет запросами к серверному приложению или сценарию, а также работает с возвращенными данными из этого серверного компонента. Каждое Ajax-приложение использует объект XMLHttpRequest, поэтому вы должны быть очень близко знакомы с ним, для того чтобы заставить ваши Ajax-приложения выполняться и выполняться хорошо.

В этой статье я выйду за границы представленных в предыдущей статье основ и сконцентрируюсь более детально на трех ключевых частях этого объекта:

  • Состояние готовности HTTP
  • Код состояния HTTP
  • Типы запросов, которые вы можете сделать

Каждый из них является, как правило, частью структуры запроса; в результате о них известно мало подробностей. Однако вы должны свободно разбираться в состояниях готовности, кодах состояния и запросах, если хотите не просто поиграть в Ajax-программирование, а сделать больше. Когда в вашем приложении что-то идет не так (все всегда идет не так), знание кодов состояния, способов передачи HEAD-запроса или того, что означает код состояния 400, может вылиться в разницу между пятью минутами отладки и пятью часами разочарования и замешательства.

XMLHttpRequest или XMLHttp

Microsoft™ и Internet Explorer использует объект XMLHttp вместо объекта XMLHttpRequest, используемого в браузерах Mozilla, Opera, Safari и большинстве остальных браузеров. Ради простоты я буду ссылаться на оба этих объекта просто как XMLHttpRequest. Это соответствует общепринятой практике в Web и также совпадает с намерениями Microsoft использовать XMLHttpRequest в качестве имени объекта запроса в Internet Explorer 7.0 (более подробно об этом – во второй части).

Сначала рассмотрим состояния готовности HTTP.

Подробно о состояниях готовности HTTP

Вы должны помнить из предыдущей статьи, что объект XMLHttpRequest имеет свойство readyState. Это свойство удостоверяет, что сервер завершил запрос, и обычно функция обратного вызова использует данные от сервера для обновления Web-формы или страницы. В листинге 1 приведен простой пример этого (также в последней статье этой серии – смотрите раздел Ресурсы).

Листинг 1. Работа с ответом сервера в функции обратного вызова
 function updatePage() {
   if (request.readyState == 4) {
     if (request.status == 200) {
       var response = request.responseText.split("|");
       document.getElementById("order").value = response[0];
       document.getElementById("address").innerHTML =
         response[1].replace(/\n/g, "<br />");
     } else
       alert("status is " + request.status);
   }
 }

Это определенно наиболее общее (и наиболее простое) использование состояний готовности. Как вы, возможно, догадались по числу "4", существует и несколько других состояний готовности (список приведен в последней статье этого цикла статей – см. раздел Ресурсы):

  • 0: Запрос не инициализирован (перед вызовом open()).
  • 1: Запрос инициализирован, но не был передан (перед вызовом send()).
  • 2: Запрос был передан и обрабатывается (на данном этапе вы можете обычно получить заголовки содержимого из ответа).
  • 3: Запрос обрабатывается; часто в ответе доступны некоторые частичные данные, но сервер не закончил свой ответ.
  • 4: Ответ завершен; вы можете получить ответ сервера и использовать его.

Если вы хотите выйти за рамки основ Ajax-программирования, то должны знать не только эти состояния, но и когда они возникают, а также как вы можете использовать их. Первое и самое главное – вы должны изучить, на каком этапе запроса возникает каждое состояние. К сожалению, это не такая уж интуитивная вещь, и имеются специальные случаи.

Скрытые значения состояний готовности

Первое состояние готовности, обозначаемое значением свойства readyState равным 0 (readyState == 0), представляет неинициализированный запрос. Как только вы вызовете метод open() вашего объекта запроса, это свойство устанавливается в 1. Поскольку вы почти всегда вызываете open() сразу после инициализации вашего запроса, редко можно увидеть readyState == 0. Более того, неинициализированное состояние готовности достаточно бесполезно в реальных приложениях.

Тем не менее, в интересах полноты изложения взгляните на листинг 2, в котором показано, как получить состояние готовности, когда оно установлено в 0.

Листинг 2. Получение состояния готовности 0
   function getSalesData() {
     // Создать объект request
     createRequest();		
     alert("Ready state is: " + request.readyState);

     // Настроить  (инициализировать) запрос
     var url = "/boards/servlet/UpdateBoardSales";
     request.open("GET", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

В этом простом примере getSalesData() – это функция, которую вызывает ваша Web-страница для запуска запроса (как при нажатии кнопки). Обратите внимание, что вы должны проверить состояние готовности перед вызовом open(). На рисунке 1 sпоказан результат выполнения этого приложения.

Рисунок 1. Состояние готовности 0
Рисунок 1. Состояние готовности 0

Когда 0 равен 4

В том случае, когда несколько JavaScript-функций используют один и тот же объект запроса, проверка на равенство 0 состояния готовности (для гарантии того, что объект еще не используется) может вызвать проблемы. Поскольку readyState == 4 указывает на завершенность запроса, вы часто сможете найти неиспользуемые объекты, имеющие состояние готовности все еще равное 4 – данные от сервера были использованы, но ничего после этого не произошло для сброса состояния готовности. Существует функция, сбрасывающая состояние готовности объекта запроса, - это функция abort(), но она предназначена не для этого. Если вам нужны несколько функций, возможно, лучшим вариантом будет создание и использование объекта запроса для каждой функции, а не общее использование одного объекта.

Очевидно, это не очень хорошо; существует очень мало случаев, когда вы должны проверять, что open() не была вызвана. Единственным использованием этого состояния готовности в "почти реальном" Ajax-программировании будет ситуация, когда вы выполняете несколько запросов, используя один и то же объект XMLHttpRequest из нескольких функций. В этой ситуации (довольно необычной) вы, возможно, захотите убедиться, что объект запроса находится в неинициализированном состоянии (readyState == 0) перед выполнением новых запросов. Это, в сущности, гарантирует, что другая функция не использует объект в это же время.

Обзор состояния готовности выполняющегося запроса

От состояния готовности 0 ваш объект запроса должен проходить через каждое другое состояние в обычном запросе и ответе, и, в конце концов, закончить на состоянии 4. Вот почему вы видите строку кода if (request.readyState == 4) в большинстве функций обратного вызова; она гарантирует, что сервер закончил свою работу с запросом и можно без опасений обновить Web-страницу или выполнить действие, основанное на полученных от сервера данных.

Увидеть этот процесс во время его протекания является тривиальной задачей. Вместо выполняющегося только при состоянии готовности равном 4 кода в вашей функции обратного вызова просто выводите состояние готовности каждый раз при вызове функции. Пример приведен в листинге 3.

Листинг 3. Проверка состояния готовности
   function updatePage() {
     // Отобразить текущее состояние готовности
     alert("updatePage() called with ready state of " + request.readyState);
   }

Вы должны создать функцию для вызова из вашей Web-страницы и передать в ней запрос серверному компоненту (просто такая же функция, как и приведенная в листинге 2, а также в примерах первой и второй статей данного цикла статей). Убедитесь в том, что при настройке вашего запроса вы установили функцию обратного вызова в updatePage(); для этого установите свойство onreadystatechange вашего объекта запроса в updatePage().

Этот код является отличной иллюстрацией того, что на самом деле означает onreadystatechange – каждый раз при изменении состояния готовности запроса вызывается updatePage(), и вы видите предупреждение. На рисунке 2 показан пример вызова этой функции, в данном случае с состоянием готовности 1.

Рисунок 2. Состояние готовности 1
Рисунок 2. Состояние готовности 1

Попробуйте этот код самостоятельно. Поместите его на вашу Web-страницу и активизируйте ваш обработчик событий (нажмите кнопку, выйдите из поля или используйте любой метод, который вы установили для инициирования запроса). Ваша функция обратного вызова выполнится несколько раз (каждый раз при изменении состояния готовности запроса), и вы увидите предупреждение для каждого состояния. Это наилучший способ следовать за запросом через каждое его состояние.

Несовместимость браузеров

Получив общее понятие об этом процессе, попробуйте обратиться к вашей Web-странице из нескольких различных браузеров. Вы должны заметить некоторую несовместимость в том, как обрабатываются эти состояния готовности. Например, в Firefox 1.5 вы увидите следующие состояния готовности:

  • 1
  • 2
  • 3
  • 4

Это не должно быть сюрпризом, поскольку здесь представлено каждое состояние запроса. Однако если вы обратитесь к этому же приложению в Safari, вы должны увидеть (или скорее, не увидеть) кое-что интересное. Вот состояния в Safari 2.0.1:

  • 2
  • 3
  • 4

Safari на самом деле пропускает первое состояние, и нет здравого объяснения, почему; просто Safari работает таким образом. Это также выявляет важный момент: в то время как использование значения состояния запроса равное 4 перед использованием данных от сервера является неплохой идеей, написание кода, зависящего от каждого промежуточного состояния готовности, несомненно, путь к получению различных результатов в различных браузерах.

Например, при использовании Opera 8.5, отображение состояний готовности становится даже еще хуже:

  • 3
  • 4

И последнее, но важное - Internet Explorer отображает следующие состояния:

  • 1
  • 2
  • 3
  • 4

Если с запросом имеются проблемы, это самое первое место, где следует их искать. Добавьте вывод предупреждения, чтобы увидеть состояние готовности запроса и убедиться в том, что все работает нормально. Еще лучше - протестируйте и в Internet Explorer, и в Firefox – вы получите все четыре состояния готовности и сможете проверить каждый этап запроса.

Теперь посмотрим со стороны ответа.

Данные ответа под микроскопом

Разобравшись с различными состояниями готовности, происходящими во время запроса, вы готовы исследовать другую важную часть объекта XMLHttpRequest – свойство responseText. Вспомните из последней статьи, что это свойство используется для получения данных от сервера. Как только сервер завершит обработку запроса, он размещает все данные, необходимые для ответа на запрос, в свойство responseText запроса. После этого ваша функция обратного вызова может использовать эти данные, как показано в листингах 1 и 4.

Листинг 4. Использование ответа от сервера
   function updatePage() {
     if (request.readyState == 4) {
       var newTotal = request.responseText;
       var totalSoldEl = document.getElementById("total-sold");
       var netProfitEl = document.getElementById("net-profit");
       replaceText(totalSoldEl, newTotal);

       /* Определить новую чистую прибыль */
       var boardCostEl = document.getElementById("board-cost");
       var boardCost = getText(boardCostEl);
       var manCostEl = document.getElementById("man-cost");
       var manCost = getText(manCostEl);
       var profitPerBoard = boardCost - manCost;
       var netProfit = profitPerBoard * newTotal;

       /* Обновить чистую прибыль на форме продаж */
       netProfit = Math.round(netProfit * 100) / 100;
       replaceText(netProfitEl, netProfit);
     }

Листинг 1 довольно прост. Листинг 4 немного более сложен, но в начале оба проверяют состояние готовности и затем извлекают значение (или значения) из свойства responseText.

Просмотр текстового ответа во время запроса

Аналогично состоянию готовности значение свойства responseText изменяется на всем протяжении жизненного цикла запроса. Чтобы увидеть это в действии, используйте код, аналогичный приведенному в листинге 5, для тестирования текстового ответа, также как и состояния готовности.

Листинг 5. Тестирование свойства responseText
   function updatePage() {
     // Отобразить текущее состояние готовности
     alert("updatePage() called with ready state of " + request.readyState +
           " and a response text of '" + request.responseText + "'");
     }

Теперь откройте ваше Web-приложение в браузере и активируйте запрос. Для получения наибольшей информации из этого кода используйте либо Firefox, либо Internet Explorer, поскольку оба обрабатывают все возможные состояния готовности во время запроса. Например, когда состояние готовности равно 2, свойство responseText не определено (см. рисунок 3); вы должны увидеть ошибку, если открылась консоль JavaScript.

Рисунок 3. Текстовый ответ при состоянии готовности 2
Рисунок 3. Текстовый ответ при состоянии готовности 2

А при состоянии готовности 3 сервер поместил значение в свойство responseText, по крайней мере, в этом примере (см. рисунок 4).

Рисунок 4. Текстовый ответ при состоянии готовности 3
Рисунок 4. Текстовый ответ при состоянии готовности 3

Вы увидите, что ваши ответы при состоянии готовности 3 отличаются от сценария к сценарию, от сервера к серверу и от браузера к браузеру. Но все же этот подход продолжает оставаться чрезвычайно полезным при отладке вашего приложения.

Получение надежных данных

Во всей документации и спецификациях утверждается, что только при состоянии готовности 4 данные можно использовать безопасно. Поверьте мне, вы редко найдете случаи, когда данные не могут быть получены из свойства responseText при состоянии готовности равном 3. Однако полагаться на это в вашем приложении – плохая идея. Если вы напишете код, зависящий от завершенности данных при состоянии готовности 3, почти гарантируется, что наступит момент, когда данные будт не полны.

Лучшей идеей является предоставление некоторого рода обратной связи с пользователем – когда состояние готовности равно 3, отобразить, что ответ на подходе. В то время, как использование такой функции как alert(), очевидно, плохая идея, использование Ajax и блокирование пользователя диалоговым окном понять довольно трудно – вы могли бы обновить поле на вашей форме или странице при изменении состояния готовности. Например, попробуйте установить длину индикатора хода процесса в 25% при равенстве состояния готовности 1, 50% при 2, 75% при 3 и 100% (завершено) при 4.

Естественно, такой подход понятнее, но зависит от используемого браузера. В Opera вы никогда не получите первых двух состояний готовности, а Safari пропустит 1. По этой причине я оставляю этот пример как упражнение и не включаю в эту статью.

Время взглянуть на коды состояния.

Пристальный взгляд на коды состояния HTTP

Имея в багаже знаний ваш опыт Ajax-программирования состояния готовности и ответа сервера, вы готовы добавить еще один уровень усовершенствования Ajax-приложений – работу с кодами состояния HTTP. Эти коды не являются чем-то новым для Ajax. Они существуют в Web со времен его появления. Вы, вероятно, уже видели некоторые из них в вашем браузере

  • 401: Unauthorized (Не авторизован)
  • 403: Forbidden (Запрещен)
  • 404: Not Found (Не найден)

Можно найти еще (ссылка на полный список приведена в разделе Ресурсы). Для добавления еще одного уровня управляемости и оперативности (и особенно более надежной обработки ошибок) к вашим Ajax-приложениям необходимо проверять коды состояния в запросе и ответе соответственно.

200: Все OK

Во многих Ajax-приложениях вы увидите функцию обратного вызова, проверяющую состояние готовности и продолжающую работу с данными ответа сервера, как в листинге 6.

Листинг 6. Функция обратного вызова, игнорирующая код состояния
   function updatePage() {
     if (request.readyState == 4) {
       var response = request.responseText.split("|");
       document.getElementById("order").value = response[0];
       document.getElementById("address").innerHTML =
         response[1].replace(/\n/g, "<br />");
     }
   }

Это недальновидный и подверженный ошибкам подход к Ajax-программированию. Если сценарий требует аутентификации, а ваш запрос не предоставляет корректных данных, сервер возвратит код ошибки 403 или 401. Однако состояние готовности будет установлено в 4, поскольку сервер ответил на запрос (даже если ответ на ваш запрос не такой, какой вы хотели или ожидали). В результате пользователь не получит правильных данных и может даже получить неприятную ошибку, когда ваш JavaScript-код попытается использовать несуществующие серверные данные.

Гарантировать то, что сервер не только завершил обработку запроса, но и возвратил код состояния "Все в порядке", требует минимальных усилий. Этот код равен "200" и возвращается в свойстве status объекта XMLHttpRequest. Итак, добавьте дополнительную строку в вашу функцию обратного вызова, как показано в листинге 7.

Листинг 7. Проверка кода состояния
   function updatePage() {
     if (request.readyState == 4) {
       if (request.status == 200) {
         var response = request.responseText.split("|");
         document.getElementById("order").value = response[0];
         document.getElementById("address").innerHTML =
           response[1].replace(/\n/g, "<br />");
       } else
         alert("status is " + request.status);
     }
   }

С этими небольшим числом дополнительных строк кода вы можете быть уверены, что если что-то пойдет не так, ваши пользователи получат (под вопросом) полезное сообщение об ошибке вместо страницы с искаженными данными без всяких объяснений.

Переадресация и перенаправление

Перед детальным рассмотрением ошибок имеет смысл поговорить о том, о чем вы, возможно, не должны беспокоиться при использовании Ajax – переадресации. В кодах состояния HTTP есть семейство кодов состояния 300, включающих:

  • 301: Moved permanently (Перемещен постоянно)
  • 302: Found (Найден) - запрос переадресован на другой URL/URI
  • 305: Use Proxy (Использовать прокси) - запрос должен использовать прокси для доступа к затребованному ресурсу

Ajax-программисты, возможно, не беспокоятся о переадресации по двум причинам:

  • Прежде всего, Ajax-приложения почти всегда пишутся для конкретного серверного сценария, сервлета или приложения. Исчезновение или перемещение в другое место этого компонента без вашего, Ajax-программиста, ведома встречается довольно редко. Поэтому почти всегда вы знаете, что ресурс переместился (потому что вы его переместили, или он уже был перемещен), меняете URL в вашем запросе и никогда не сталкиваетесь с такого рода проблемами.
  • И еще одна, даже более важная, причина: Ajax-приложения и запросы выполняются в "песочнице" безопасности. Это значит, что доменом, обслуживающим Web-страницу, с которой выполняются Ajax-запросы, является домен, который должен на них отвечать. Поэтому Web-страница, обслуживаемая ebay.com, не может выполнить Ajax-запрос сценарию, выполняющемуся на amazon.com; Ajax-приложения ibm.com не могут выполнять запросы сервлетам, работающим на netbeans.org.

В результате ваши запросы не могут быть переадресованы на другой сервер без генерирования ошибки защиты. В этих случаях вы вовсе не получите код состояния. Вы просто получите ошибку JavaScript в консоли отладки. Поэтому, думая о многообразии кодов состояния, вы можете почти совершенно игнорировать коды переадресации.

Крайние ситуации и тяжелые ситуации

На данный момент программисты-новички могут удивиться, из-за чего здесь весь этот шум. Совершенно ясно, что менее 5 процентов Ajax-запросов требуют работы с состояниями готовности 2 и 3 и с кодами состояния аналогичными 403 (на самом деле возможно ближе к 1 проценту или меньше). Эти случаи важны и называются крайними случаями – редкими ситуациями, которые возникают при совпадении очень необычных условий. Оставаясь редкими, крайние случаи могут быть причиной до 80 процентов наибольших пользовательских разочарований!

Обычные пользователи забывают 100 случаев, когда приложение работало правильно, но ясно помнят один, когда оно работало не правильно. Если вы можете обработать крайние случаи (и тяжелые случаи) незаметно, ваши пользователи будут довольны и вернутся на ваш сайт.

Ошибки

Как только вы позаботились о коде состояния 200 и поняли, что можете в значительной степени проигнорировать 300-е семейство кодов состояния, единственной группой кодов, о которой надо подумать – это 400-е семейство, указывающее на ошибки различного типа. Повторно взгляните на листинг 7 и обратите внимание, что хотя ошибки и обрабатываются, пользователю выдается очень общее сообщение об ошибке. И хотя это шаг в правильном направлении, это сообщение все еще остается бесполезным с точки зрения информирования пользователя или программиста, работающего с приложением, о том, что произошло.

Прежде всего, добавьте поддержку отсутствующих страниц. Они действительно не должны часто появляться в реальных системах, но это нередко случается при тестировании перемещенного сценария или при вводе программистом неверного URL. Если вы можете изящно обрабатывать ошибки 404, то намного лучше поможете поставленным в тупик пользователям и программистам. Например, если сценарий был удален с сервера, а вы используете приведенный в листинге 7 код, вы должны увидеть ничего не объясняющее сообщение об ошибке, показанное на рисунке 5.

Рисунок 5. Общая обработка ошибок
Рисунок 5. Общая обработка ошибок

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

Листинг 8. Проверка кода состояния
   function updatePage() {
     if (request.readyState == 4) {
       if (request.status == 200) {
         var response = request.responseText.split("|");
         document.getElementById("order").value = response[0];
         document.getElementById("address").innerHTML =
           response[1].replace(/\n/g, "<br />");
       } else if (request.status == 404) {
         alert ("Requested URL is not found.");
       } else if (request.status == 403) {
         alert("Access denied.");
       } else
         alert("status is " + request.status);
     }
   }

Это все довольно просто, но действительно предоставляется дополнительная информация. На рисунке 6 показана эта же ошибка, что и на рисунке 5, но в данном случае код обработки ошибок выдает пользователю или программисту лучшую картину того, что случилось.

Рисунок 6. Индивидуальная обработка ошибок
Рисунок 6. Индивидуальная обработка ошибок

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

Дополнительные типы запроса

Если вы действительно хотите управлять объектом XMLHttpRequest, рассмотрим еще одну, последнюю тему. Добавьте HEAD-запросы в ваш репертуар. В первых двух статьях я рассказал, как выполнять GET-запросы; в следующей статье вы научитесь всему, что связано с передачей данных на сервер при помощи POST-запроса. В духе усовершенствованной обработки ошибок и сбора информации вы должны научиться выполнять HEAD-запросы.

Выполнение запроса

В действительности выполнение HEAD-запроса является довольно тривиальной задачей; вы просто вызываете метод open() с "HEAD" вместо "GET" или "POST" в качестве первого параметра, как показано в листинге 9.

Листинг 9. Выполнение HEAD-запроса с Ajax
   function getSalesData() {
     createRequest();
     var url = "/boards/servlet/UpdateBoardSales";
     request.open("HEAD", url, true);
     request.onreadystatechange = updatePage;
     request.send(null);
   }

При выполнении подобного HEAD-запроса сервер не возвращает реальный ответ, как для GET или POST-запросов. Вместо этого сервер должен только возвратить заголовки ресурса, в которые включается последнее время модификации содержимого запроса, месторасположение запрашиваемого ресурса и довольно много другой интересной информации. Вы можете использовать эту информацию о ресурсе еще до того, как сервер должен будет обработать и возвратить этот ресурс.

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

Листинг 10. Вывод всех заголовков ответа их HEAD-запроса
   function updatePage() {
     if (request.readyState == 4) {
       alert(request.getAllResponseHeaders());
     }
   }

На рисунке 7 показаны заголовки ответа из простого Ajax-приложения, выполняющего HEAD-запрос на сервер.

Рисунок 7. Заголовки ответа из HEAD-запроса
Рисунок 7. Заголовки ответа из HEAD-запроса

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

Проверка URL

Вы увидели, как проверить ошибку 404 при отсутствии URL. Если это превращается в общую проблему (возможно, определенный сценарий или сервлет в данный момент времени находитcя в режиме offline) – вы, вероятно, захотите проверить URL перед выполнением полного GET или POST-запроса. Для этого выполните HEAD-запрос и проверьте 404-ю ошибку в вашей функции обратного вызова; в листинге 11 приведен пример такой функции.

Листинг 11. Проверка существования URL
   function updatePage() {
     if (request.readyState == 4) {
       if (request.status == 200) {
         alert("URL exists");
       } else if (request.status == 404) {
         alert("URL does not exist.");
       } else {
         alert("Status is: " + request.status);
       }
     }
   }

По правде говоря, это имеет небольшое значение. Сервер должен ответить на запрос и обработать его для заполнения значения длины содержимого заголовка ответа, поэтому вы не экономите время обработки. Кроме того, выполнение запроса и определение существования URL при помощи HEAD-запроса занимает столько же времени, сколько и выполнение GET или POST-запроса и последующая обработка ошибок (как показано в листинге 7. Хотя иногда может быть полезно знать точно, что доступно; вы никогда не знаете, когда вас пробьет на творчество и вам понадобится HEAD-запрос!

Полезные HEAD-запросы

Одной из ситуаций, когда HEAD-запрос может оказаться полезным, является необходимость узнать длину содержимого, или даже его тип. Это позволяет определить, будет ли возвращен процессу большой объем данных, или сервер будет пытаться возвратить двоичные файлы вместо HTML, текстовых данных или XML (которые намного проще обработать в JavaScript, чем двоичные данные).

В таких случаях вы просто используете соответствующее имя заголовка и передаете его в метод getResponseHeader() объекта XMLHttpRequest. То есть, для получения длины ответа вызовите request.getResponseHeader("Content-Length");. Для получения типа содержимого используйте request.getResponseHeader("Content-Type");.

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

В заключение

Для многих Ajax и Web-программистов материал, представленный в этой статье, может показаться довольно сложным. Какое значение имеет выполнение HEAD-запроса? Когда действительно нужно обрабатывать коды состояния для переадресации в вашем JavaScript? Это хорошие вопросы: для простых приложений ответ состоит в том, что эти продвинутые технические приемы вряд ли имеют большую ценность.

Однако Web больше не является местом, где допускаются простые приложения; пользователи становятся все более опытными, клиенты ожидают устойчивости и развитой системы отчета об ошибках, менеджеров увольняют из-за того, что приложение не работает более 1% времени.

Это ваша работа, в конце концов, выйти за рамки простого приложения, и это потребует более глубокого знания XMLHttpRequest.

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

Цель этой статьи не в том, чтобы сделать ваши приложения броскими, помочь вам выделить текст затухающей желтой подсветкой или придать им поведение настольных приложений. Хотя в этом и заключается мощь Ajax (эти темы мы рассмотрим в последующих статьях), это в какой то степени просто украшательства. Если вы можете использовать Ajax для создания монолитной основы, в которой ваше приложение надежно обрабатывает ошибки и проблемы, пользователи будут возвращаться на ваш сайт. Добавьте к этому визуальные трюки, которые я рассмотрю в последующих статьях, и ваши пользователи будут заинтригованы, взволнованы и счастливы. Серьезно, не пропустите следующую статью!


Загрузка

ОписаниеИмяРазмер
Example code for this articlewa-ajaxintro3_ajax-xhr_adv.zip183KB

Ресурсы

Научиться

Получить продукты и технологии

  • Книга Элизабет Фримен, Эрика Фримена и Брета Маклафлина Head Rush Ajax (O'Reilly Media, Inc., февраль 2006) берет идеи, выделенные в этой статье, и загружает их в вашу голову в стиле "Head First" (Вперед с головой).
  • Java и XML, вторая редакция, Брет Маклафлин (Август 2001, O'Reilly Media, Inc.) - содержит обсуждение автором преобразований XHTML и XML.
  • JavaScript: Полное руководство, Дэвид Флэнаган (ноябрь 2001, O'Reilly Media, Inc.) – содержит исчерпывающие инструкции по работе с JavaScript, динамическими Web-страницами, а в готовящемся издании добавлены две главы по Ajax.
  • Вперед головой в HTML с CSS и XHTML, Элизабет и Эрик Фримены (декабрь 2005, O'Reilly Media, Inc.) – полный источник информации о XHTML и CSS, а также о том, как их объединить.
  • Пробное программное обеспечение IBM: Создайте ваш следующий проект с программным обеспечением, доступным для загрузки непосредственно с developerWorks.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, XML, Технология Java
ArticleID=188031
ArticleTitle=Освоение Ajax: Часть 3. Усовершенствованные запросы и ответы в Ajax
publish-date=02142006