******************************************
18.1.2. Получение ответа
Полный HTTP-ответ содержит код состояния, набор заголовков ответа и тело ответа. Все это доступно в виде свойств и методов объекта
<b>XMLHttpRequest</b>
:
• Свойства
<b>status</b>
и
<b>statusText</b>
возвращают код состояния HTTP в числовом и текстовом виде. Эти свойства хранят стандартные HTTP-значения, такие как 200 и «ОК» в случае успешного выполнения запроса или 404 и «Not Found» при попытке обратиться к ресурсу, отсутствующему на сервере.
• Заголовки ответа можно получить с помощью методов
<b>getResponseHeader()</b>
и
<b>getAllResponseHeaders().</b>
Обработка cookies выполняется объектом
<b>XMLHttpRequest</b>
автоматически: он исключает заголовки «Cookie» из множества, возвращаeмого методом
<b>getAllResponseHeaders(),</b>
и возвращает null, если передать аргумент «Set-Cookie» или «Set-Cookie2» методу
<b>getResponseHeader().</b>
• Тело ответа в текстовом виде доступно через свойство
<b>responseText</b>
или в виде объекта
<b>Document</b>
через свойство
<b>responseXML</b>
. (Выбор такого имени свойства объясняется историческими причинами: фактически оно предназначено для работы с XHTML- и XML-документами, но спецификация «ХНН2» определяет, что оно также должно работать с обычными HTML-документами.) Более подробно о свойстве
<b>responseXML</b>
рассказывается в разделе 18.1.2.2.
Обычно объект
<b>XMLHttpRequest</b>
используется в асинхронном режиме (но загляните в раздел 18.1.2.1): метод
<b>send()</b>
возвращает управление сразу же после отправки запроса, поэтому методы и свойства, перечисленные выше, не могут использоваться до фактического получения ответа. Чтобы определить момент получения ответа, необходимо обрабатывать событие «readystatechange» (или событие «progress», определяемое новой спецификацией «ХНН2» и описываемое в разделе 18.1.4), возбуждаемое в объекте
<b>XMLHttpRequest</b>
. Но, чтобы понять, как обрабатывать это событие, необходимо сначала разобраться со свойством
<b>readyState</b>
.
Свойство
<b>readyState</b>
- это целочисленное значение, определяющее код состояния HTTP-запроса; его возможные значения перечислены в табл. 18.1. Идентификаторы, указанные в первой колонке, - это константы, определяемые конструктором
<b>XMLHttpRequest</b>
. Эти константы являются частью спецификации
<b>XMLHttpRequest</b>
, но старые версии броузеров и ІE8 не определяют их, поэтому часто можно увидеть программный код, в котором вместо константы
<b>XMLHttpRequest.DONE</b>
используется числовое значение 4.
Теоретически событие «readystatechange» генерируется всякий раз, когда изменяется значение свойства
<b>readyState</b>
. На практике же событие может не возбуждаться, когда свойство
<b>readyState</b>
получает значение 0 или 1. Оно часто возбуждается при вызове метода
<b>send(),</b>
даже при том, что свойство
<b>readyState</b>
по-прежнему содержит значение
<b>OPENED</b>
. Некоторые броузеры возбуждают событие множество раз для состояния
<b>LOADING</b>
, чтобы обеспечить обратную связь. Все броузеры возбуждают событие «readystatechange», когда завершается прием ответа сервера и свойство
<b>readyState</b>
получает значение 4. Так как это событие может возбуждаться еще до завершения приема ответа, обработчики события «readystatechange» всегда должны проверять значение свойства
<b>readyState</b>
.
Чтобы обрабатывать события «readystatechange», нужно присвоить функцию обработчика события свойству
<b>onreadystatechange</b>
объекта
<b>XMLHttpRequest</b>
. Можно также воспользоваться методом
<b>addEventListener()</b>
(или
<b>attachEvent()</b>
в IE версии 8 и ниже), но обычно для обработки запроса бывает вполне достаточно одного обработчика, поэтому проще установить свойство
<b>onreadystatechange</b>
.
Пример 18.2 определяет функцию
<b>getText(),</b>
которая демонстрирует особенности обработки событий «ready statechange». Обработчик события сначала проверяет завершение запроса. После этого он проверяет код состояния ответа и убеждается в успешном выполнении. Затем он извлекает заголовок «Content-Type», чтобы убедиться, что получен ответ ожидаемого типа. Если выполняются все три условия, он передает тело ответа (в виде текста) указанной функции обратного вызова.
Пример 18.2. Получение HTTP-ответа в обработчике
<b>onreadystatechange</b>
<b>// Выполняет запрос HTTP GET содержимого указанного URL-адреса.</b>
<b>// После успешного получения ответа проверяет, содержит ли он простой текст,</b>
<b>// и передает его указанной функции обратного вызова </b>
<b>function getText(url, callback) {</b>
<b> var request = new XMLHttpRequest(); // Создать новый запрос</b>
<b> request.open("GET", url); // Указать URL-адрес ресурса</b>
<b> request.onreadystatechange = function() {</b>
<b> // Определить обработчик события</b>
<b> // Если запрос был выполнен успешно</b>
<b> if (request.readyState === 4 && request.status === 200) {</b>
<b> var type = request.getResponseHeader("Content-Type");</b>
<b> if (type.fnatch(/~text/)) // Убедиться, что это текст</b>
<b> callback(request.responseText); // Передать функции</b>