JavaScript. Подробное руководство, 6-е издание, стр. 279

<b>    }</b>

<b>  };</b>

<b>  request.send(null); // Отправить запрос</b>

<b>}</b>

18.1.2.1. Получение синхронного ответа

Сама природа HTTP-ответа предполагает их асинхронную обработку. Тем не менее объект

<b>XMLHttpRequest</b>
поддерживает возможность получения ответов в синхронном режиме. Если в третьем аргументе передать методу
<b>open()</b>
значение false, выполнение метода
<b>send()</b>
будет заблокировано до завершения запроса. В этом случае отпадает необходимость использовать обработчик события: после того как метод
<b>send()</b>
вернет управление, можно будет сразу же проверить свойства
<b>status</b>
и
<b>responseText</b>
объекта
<b>XMLHttpRequest</b>
. Сравните следующую синхронную реализацию функции
<b>getText()</b>
из примера 18.2:

<b>// Выполняет синхронный запрос HTTP GET содержимого по указанному URL-адресу.</b>

<b>// Возвращает текст ответа. Возбуждает исключение в случае неудачи </b>

<b>// или если ответ не является текстом, </b>

<b>function getTextSync(url) {</b>

<b>  var request = new XMLHttpRequest(); // Создать новый запрос</b>

<b>  request.open( &quot;GET&quot;, url, false); // false - синхронный режим</b>

<b>  request.send(null); // Отправить запрос</b>

<b>  // Возбудить исключение, если код состояния не равен 200</b>

<b>  if (request.status !== 200) throw new Error(request.statusText);</b>

<b>  // Возбудить исключение, если ответ имеет недопустимый тип</b>

<b>  var type = request.getResponseHeader(&quot;Content-Type&quot;);</b>

<b>  if (!type.match(/~text/))</b>

<b>    throw new Error(&quot;Ожидался текстовый ответ; получен: &quot; + type);</b>

<b>  return request.responseText;</b>

<b>}</b>

Синхронные запросы выглядят весьма заманчиво, однако использовать их нежелательно. Интерпретатор JavaScript на стороне клиента выполняется в единственном потоке, и когда метод

<b>send()</b>
блокируется, это обычно приводит к зависанию пользовательского интерфейса всего броузера. Если сервер, к которому выполнено подключение, отвечает на вопросы с задержкой, броузер пользователя будет зависать. Тем не менее в разделе 22.4 вы познакомитесь с одним из случаев, когда синхронные запросы вполне допустимы.

18.1.2.2. Декодирование ответа

В примерах выше предполагалось, что сервер возвращает ответ в виде простого текста, с MIME-типом «text/ріаіп», «text/html» или «text/css», и мы извлекаем его из свойства

<b>responseText</b>
объекта
<b>XMLHttpRequest</b>
.

Однако существуют и другие способы обработки ответов сервера. Если сервер посылает в ответе XML- или XHTML-документ, разобранное представление XML-документа можно получить из свойства

<b>responseXML</b>
. Значением этого свойства является объект
<b>Document</b>
, при работе с которым можно использовать приемы, представленные в главе 15. (Проект спецификации «XHR2» требует, чтобы броузеры автоматически выполняли синтаксический анализ ответов типа «text/html» и также делали их доступными через свойство
<b>responseXML</b>
в виде объектов Document, но на момент написания этих строк это требование не было реализовано в текущих броузерах.)

Если в ответ на запрос серверу потребуется отправить структурированные данные, такие как объект или массив, он может передать данные в виде строки в формате JSON (раздел 6.9). После получения такой строки содержимое свойства

<b>responseText</b>
можно передать методу
<b>JSON.parse().</b>
Пример 18.3 является обобщенной версией примера 18.2: он выполняет запрос методом GET по указанному URL-ад-ресу и после получения содержимого этого адреса передает его указанной функции обратного вызова. Но теперь функции не всегда будет передаваться простой текст - ей может быть передан объект
<b>Document</b>
, объект, полученный с помощью
<b>JSON.parse(),</b>
или строка.

Пример 18.3. Синтаксический анализ НТТР-ответа

<b>// Выполняет запрос HTTP GET на получение содержимого по указанному URL-адресу.</b>

<b>// При получении ответа он передается функции обратного вызова </b>

<b>// как разобранный объект XML-документа, объект JS0N или строка, </b>

<b>function get(url, callback) {</b>

<b>  var request = new XMLHttpRequest(); // Создать новый запрос</b>

<b>  request.open(&quot;GET&quot;, url); // Указать URL-адрес ресурса</b>

<b>  request.onreadystatechange = function() { // Определить обработчик события</b>

<b>    // Если запрос был выполнен и увенчался успехом</b>

<b>    if (request.readyState === 4 &amp;&amp; request.status === 200) {</b>

<b>      // Определить тип ответа</b>

<b>      var type = request.getResponseHeader(&quot;Content-Type&quot;);</b>

<b>      // Проверить тип, чтобы избежать в будущем передачи ответа</b>

<b>      // в виде документа в формате HTML</b>

<b>      if (type.index0f(&quot;xml&quot;) !== -1 &amp;&amp; request.responseXML)</b>

<b>        callback(request.responseXML); // Объект XML</b>