Javascript — синхронный ajax запрос (xmlhttprequest)

«Непростые» запросы

В кросс-доменном можно указать не только , но и любой другой метод, например , .

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

Чтобы пресечь любые недопонимания, браузер использует предзапрос в случаях, когда:

  • Если метод – не GET / POST / HEAD.
  • Если заголовок имеет значение отличное от , или , например .
  • Если устанавливаются другие HTTP-заголовки, кроме , , .

…Любое из условий выше ведёт к тому, что браузер сделает два HTTP-запроса.

Первый запрос называется «предзапрос» (английский термин «preflight»). Браузер делает его целиком по своей инициативе, из JavaScript мы о нём ничего не знаем, хотя можем увидеть в инструментах разработчика.

Этот запрос использует метод . Он не содержит тела и содержит название желаемого метода в заголовке , а если добавлены особые заголовки, то и их тоже – в .

Его задача – спросить сервер, разрешает ли он использовать выбранный метод и заголовки.

На этот запрос сервер должен ответить статусом 200, без тела ответа, указав заголовки и, при необходимости, .

Дополнительно он может указать , где – количество секунд, на которые нужно закэшировать разрешение. Тогда при последующих вызовах метода браузер уже не будет делать предзапрос.

Давайте рассмотрим предзапрос на конкретном примере.

Рассмотрим запрос , который используется в протоколе WebDAV для управления файлами через HTTP:

Этот запрос «непростой» по двум причинам (достаточно было бы одной из них):

  1. Метод .
  2. Заголовок .

Поэтому браузер, по своей инициативе, шлёт предварительный запрос :

Обратим внимание на детали:

  • Адрес – тот же, что и у основного запроса: .
  • Стандартные заголовки запроса , , присутствуют.
  • Кросс-доменные специальные заголовки запроса:
    • – домен, с которого сделан запрос.
    • – желаемый метод.
    • – желаемый «непростой» заголовок.

На этот запрос сервер должен ответить статусом 200, указав заголовки и .

Но в протоколе WebDav разрешены многие методы и заголовки, которые имеет смысл сразу перечислить в ответе:

Ответ должен быть без тела, то есть только заголовки.

Браузер видит, что метод – в числе разрешённых и заголовок – тоже, и дальше он шлёт уже основной запрос.

При этом ответ на предзапрос он закэширует на 86400 сек (сутки), так что последующие аналогичные вызовы сразу отправят основной запрос, без .

Основной запрос браузер выполняет уже в «обычном» кросс-доменном режиме:

Ответ сервера, согласно спецификации , может быть примерно таким:

Так как содержит правильный домен, то браузер вызовет и запрос будет завершён.

Использование XMLHTTPRequest

Различают два использования XmlHttpRequest. Первое — самое простое, синхронное.

Синхронный XMLHttpRequest

В этом примере через XMLHTTPRequest с сервера запрашивается страница http://example.org/, и текст ответа сервера показывается через alert().

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', false);
xmlhttp.send(null);
if(xmlhttp.status == 200) {
  alert(xmlhttp.responseText);
}

Здесь сначала создается запрос, задается открытие () синхронного соединение с адресом /xhr/test.html и запрос отсылается с null,
т.е без данных.

При синхронном запросе браузер «подвисает» и ждет на строчке 3, пока сервер не ответит на запрос. Когда ответ получен — выполняется строка 4, код ответа сравнивается с 200 (ОК), и при помощи alert
печатается текст ответа сервера. Все максимально просто.

Свойство responseText получит такой же текст страницы, как браузер, если бы Вы в перешли на /xhr/test.html. Для сервера
GET-запрос через XmlHttpRequest ничем не отличается от обычного перехода на страницу.

Асинхронный XMLHttpRequest

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

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', true);
xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4) {
     if(xmlhttp.status == 200) {
       alert(xmlhttp.responseText);
         }
  }
};
xmlhttp.send(null);

Асинхронность включается третьим параметром функции open. В отличие от синхронного запроса, функция send() не останавливает
выполнение скрипта, а просто отправляет запрос.

Запрос xmlhttp регулярно отчитывается о своем состоянии через вызов функции xmlhttp.onreadystatechange. Состояние под номером 4 означает конец выполнения, поэтому функция-обработчик
при каждом вызове проверяет — не настало ли это состояние.

Вообще, список состояний readyState такой:

  • 0 — Unitialized
  • 1 —
  • 2 — Loaded
  • 3 — Interactive
  • 4 — Complete

Состояния 0-2 вообще не используются.

Вызов функции с состоянием Interactive в теории должен происходить каждый раз при получении очередной порции данных от сервера.
Это могло бы быть удобным для обработки ответа по частям, но Internet Explorer не дает доступа к уже полученной части ответа.

Firefox дает такой доступ, но для обработки запроса по частям состояние Interactive все равно неудобно из-за сложностей обнаружения ошибок соединения.
Поэтому Interactive тоже не используется.

На практике используется только последнее, Complete.

Если хотите углубиться в тонкости багов браузеров c readyState, отличными от 4, то многие из них рассмотрены в статье на.

Не используйте синхронные запросы

Синхронные запросы применяются только в крайнем случае, когда кровь из носу необходимо дождаться ответа сервера до продолжения скрипта. В 999 случаях из 1000
можно использовать асинхронные запросы. При этом общий алгоритм такой:

  1. Делаем асинхронный запрос
  2. Рисуем анимированную картинку или просто запись типа «Loading…»
  3. В onreadystatechange при достижении состояния 4 убираем Loading и, в зависимости от status вызываем обработку ответа или ошибки.

Кроме того, иногда полезно ставить ограничение на время запроса. Например, хочется генерировать ошибку, если запрос висит более 10 секунд.

Для этого сразу после send() через setTimeout ставится вызов обработчика ошибки, который очищается при получении ответа и обрывает запрос с генерацией ошибки,
если истекли 10 секунд.

Таймаут на синхронный запрос ставить нельзя, браузер может висеть долго-долго.. А вот на асинхронный — пожалуйста.

Этот пример демонстрирует такой таймаут.

var xmlhttp = getXmlHttp()
xmlhttp.open("POST", "/someurl", true);
xmlhttp.onreadystatechange=function(){
  if (xmlhttp.readyState != 4) return
  clearTimeout(timeout) // очистить таймаут при наступлении readyState 4
  if (xmlhttp.status == 200) {
      // Все ок
      ...
      alert(xmlhttp.responseText);
      ...
  } else {
      handleError(xmlhttp.statusText) // вызвать обработчик ошибки с текстом ответа
  }
}
xmlhttp.send("a=5&b=4");
// Таймаут 10 секунд
var timeout = setTimeout( function(){ xmlhttp.abort(); handleError("Time over") }, 10000);
function handleError(message) {
  // обработчик ошибки
  ...
  alert("Ошибка: "+message)
  ...
}

§Monitoring Download and Upload Progress

Network connectivity can be intermittent, and latency and bandwidth
are highly variable. So how do we know if an XHR request has succeeded,
timed out, or failed? The XHR object provides a convenient API for
listening to progress events (), which indicate the current status
of the request.

Event type Description

Times fired

loadstart Transfer has begun

once

progress Transfer is in progress

zero or more

error Transfer has failed

zero or once

abort Transfer is terminated

zero or once

load Transfer is successful

zero or once

loadend Transfer has finished once

Table 15-1. XHR progress events

Each XHR transfer begins with a loadstart and finishes with a
loadend event, and in between, one or more additional events are
fired to indicate the status of the transfer. Hence, to monitor progress
the application can register a set of JavaScript event listeners on the
XHR object:

var xhr = new XMLHttpRequest();
xhr.open('GET','/resource');
xhr.timeout = 5000; 

xhr.addEventListener('load', function() { ... }); 
xhr.addEventListener('error', function() { ... }); 

var onProgressHandler = function(event) {
  if(event.lengthComputable) {
    var progress = (event.loaded / event.total) * 100; 
    ...
  }
}

xhr.upload.addEventListener('progress', onProgressHandler); 
xhr.addEventListener('progress', onProgressHandler); 
xhr.send();
  1. Set request timeout to 5,000 ms (default: no timeout)

  2. Register callback for successful request

  3. Register callback for failed request

  4. Compute transfer progress

  5. Register callback for upload progress events

  6. Register callback for download progress events

Either the load or error event will fire once to
indicate the final status of the XHR transfer, whereas the
progress event can fire any number of times and provides a
convenient API for tracking transfer status: we can compare the
loaded attribute against total to estimate the amount
of transferred data.

HTTP-заголовки

умеет как указывать свои заголовки в запросе, так и читать присланные в ответ.

Для работы с HTTP-заголовками есть 3 метода:

Устанавливает заголовок запроса с именем и значением .

Например:

Ограничения на заголовки

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

не разрешено изменять их ради безопасности пользователей и для обеспечения корректности HTTP-запроса.

Поставленный заголовок нельзя снять

Ещё одной особенностью является то, что отменить невозможно.

Если заголовок определён, то его нельзя снять. Повторные вызовы лишь добавляют информацию к заголовку, а не перезаписывают его.

Например:

Возвращает значение заголовка ответа (кроме и ).

Например:

Возвращает все заголовки ответа, кроме и .

Заголовки возвращаются в виде единой строки, например:

Между заголовками всегда стоит перевод строки в два символа (независимо от ОС), так что мы можем легко разделить их на отдельные заголовки. Значение заголовка всегда отделено двоеточием с пробелом . Этот формат задан стандартом.

Таким образом, если хочется получить объект с парами заголовок-значение, нам нужно задействовать немного JS.

Вот так (предполагается, что если два заголовка имеют одинаковое имя, то последний перезаписывает предыдущий):

See also

  • MDN articles about XMLHttpRequest:
    • AJAX — Getting Started
    • Using XMLHttpRequest
    • HTML in XMLHttpRequest
  • XMLHttpRequest references from W3C and browser vendors:
    • W3C: XMLHttpRequest (base features)
    • W3C: XMLHttpRequest (latest editor’s draft with extensions to the base functionality, formerly XMLHttpRequest Level 2
    • Microsoft documentation
  • «Using the XMLHttpRequest Object» (jibbering.com)
  • XMLHttpRequest — REST and the Rich User Experience
  • HTML5 Rocks — New Tricks in XMLHttpRequest2
  • Thread on the naming convention of
  • — how to access from JSM modules etc which do not have access to DOM

    • Components.utils.importGlobalProperties
    • nsIXMLHttpRequest

GET и POST-запросы. Кодировка.

Во время обычного submit’а формы браузер сам кодирует значения полей и составляет тело GET/POST-запроса для посылки на сервер. При работе через XmlHttpRequest, это нужно делать самим, в javascript-коде. Большинство проблем и вопросов здесь связано с непониманием, где и какое кодирование нужно осуществлять.

Вначале рассмотрим общее кодирование запросов, ниже — правильную работу с русским языком для windows-1251.

Существуют два вида кодирования HTTP-запроса. Основной — urlencoded, он же — стандартное кодирование URL. Пробел представляется как %20, русские буквы и большинство спецсимволов кодируются, английские буквы и дефис оставляются как есть.

Способ, которым следует кодировать данные формы при submit’е, задается в ее HTML-таге:

<form method="get"> // метод GET с кодировкой по умолчанию
<form method="post" enctype="application/x-www-form-urlencoded"> // enctype явно задает кодировку
<form method="post"> // метод POST с кодировкой по умолчанию (urlencoded, как и предыдущая форма)

Если форма submit’ится обычным образом, то браузер сам кодирует (urlencode) название и значение каждого поля данных ( и т.п.) и отсылает форму на сервер в закодированном виде.

Формируя XmlHttpRequest, мы должны формировать запрос «руками», кодируя поля функцией .

Конечно, пропускать через encodeURIComponent стоит только те переменные, в которых могут быть спецсимволы или не английские буквы, т.е которые и будут как раз закодированы.

Например, для посылки GET-запроса с произвольными параметрами name и surname, их необходимо закодировать вот так:

// Пример с GET
...
var params = 'name=' + encodeURIComponent(name) + '&surname=' + encodeURIComponent(surname)
xmlhttp.open("GET", '/script.html?'+params, true)
...
xmlhttp.send(null)

В методе POST параметры передаются не в URL, а в теле, посылаемом через . Поэтому нужно указывать не в адресе, а при вызове

Кроме того, при POST обязателен заголовок Content-Type, содержащий кодировку. Это указание для сервера — как обрабатывать (раскодировать) пришедший запрос.

// Пример с POST
...
var params = 'name=' + encodeURIComponent(name) + '&surname=' + encodeURIComponent(surname)
xmlhttp.open("POST", '/script.html', true)
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
...
xmlhttp.send(params)

Заголовки Content-Length, Connection в POST-запросах, хотя их и содержат некоторые «руководства», обычно не нужны. Используйте их, только если Вы действительно знаете, что делаете.

Запросы multipart/form-data

Второй способ кодирования — это отсутствие кодирования. Например, кодировать не нужно для пересылки файлов. Он указывается в форме (только для POST) так:

<form method="post" enctype="multipart/form-data">

В этом случае при отправке данных на сервер ничего не кодируется. А сервер, со своей стороны, посмотрев на Content-Type(=multipart/form-data), поймет, что пришло.

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

Кодировка (языковая)

Если Вы используете только UTF-8 — пропустите эту секцию.

Все идущие на сервер параметры GET/POST, кроме случая multipart/form-data, кодируются в UTF-8. Не в кодировке страницы, а именно в UTF-8. Поэтому, например, в PHP их нужно при необходимости перекодировать функцией iconv.

<?php
// ajax.php
$name = iconv('UTF8','CP1251',$_GET);
?>

С другой стороны, ответ с сервера браузер воспринимает именно в той кодировке, которая указана в заголовке ответа Content-Type. Т.е, опять же, в PHP, чтобы браузер воспринял ответ в windows-1251 и нормально отобразил данные на странице в windows-1251,
нужно послать заголовок с кодировкой в php-коде, например так:

<?php
// ajax.php
header('Content-Type: text/plain; charset=utf-8');
?>

Или же, такой заголовок должен добавить сервер. Например, в apache автоматически добавляется кодировка опцией:

# в конфиге апача
AddDefaultCharset windows-1251

Пример 2. Обработка синхронного AJAX запроса на сервере с помощью PHP

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

В данном примере страница будет состоять из 3 кнопок. Первая кнопка будет иметь текст 1, вторая кнопка текст 2 и третья кнопка текст 3. При нажатии на любую из кнопок будет выполняться синхронный запрос на сервер. В качестве метода передачи запроса будем использовать GET. А адрес, по которому будем посылать запрос и параметры . Получать данные отправленные клиентом на сервере будем с помощью GET-переменной HTTP ($_GET). После этого полученные данные будем обрабатывать на сервере, и возвращать клиенту ответ (строку).

<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>JavaScript AJAX</title>
    <style>
      span {
        font-weight: bold;
        color: red;
      }
    </style>
  </head>
  <body>
    <p>Нажмите на одну из кнопок и получите ответ с сервера посредством технологии AJAX.</p>
    <div style="text-center;">
      <button>1</button>
      <button>2</button>
      <button>3</button>
    </div>
    <p>Ответ (AJAX): <span id="answer"></span></p>
    <script src="script.js"></script>
  </body>
</html> 
// получить все элементы button на странице
var buttons = document.getElementsByTagName("button");
// подпишемся на событие click все элементов button 
for (var i=0; i<buttons.length; i++) {
  buttons.addEventListener("click",function(){
    // создадим объект XMLHttpRequest
    var request = new XMLHttpRequest();
    //настраиваем запрос: GET - метод, ajax.php - URL-адрес по которому будет посылаться запрос, false - синхронный запрос
    //передавать параметр будем в составе URL
    request.open('GET','ajax.php?button='+this.textContent+'',false);
    // отправляем данные на сервер с помощью метода send
    request.send();
    // если статус ответа 200 (OK) то
    if (request.status==200) {
      // выведем в элемент, имеющий id="answer", ответ сервера
      document.getElementById("answer").innerHTML = request.responseText;
    }
  }	
})
<?php
// массив fructs
$fructs = array("Яблоки","Виноград","Апельсин");
// если в ассоциативном массиве $_GET существует ключ button
if (isset($_GET)) {
  // присвоим переменной $button значение из ассоциативного массива GET соответсвующее ключу button
  $button = $_GET;
  // выведем строку (ответ сервера)
  echo $fructs;
}     
?>

Options

Note that headers cannot be set on an XDomainRequest instance.

Specify whether this is a synchrounous request. Note that when
this is true the callback will be called synchronously. In
most cases this option should not be used. Only use if you
know what you are doing!

If is , then this must be a JSON-serializable object. is passed to and sent.

Number of miliseconds to wait for response. Defaults to 0 (no timeout). Ignored when is true.

Set to to send request as (see ) and parse response from JSON.

For backwards compatibility can also be a valid JSON-serializable value to be sent to the server. Additionally the response body is still parsed as JSON

For sending booleans as JSON body see FAQ

A wildcard cannot be used in the header when is true.
The header needs to specify your origin explicitly or browser will abort the request.

A function being called right before the method of the or instance is called. The or instance is passed as an argument.

Pass an object (or something that acts like one) to use instead of constructing a new one using the or constructors. Useful for testing.

Изменения состояния XHR

Если метод был вызван успешно, свойству объекта XMLHttpRequest будет присвоено значение 1 (Open). После того как заголовки HTTP-ответа были получены, для свойства readyState объекта XHR назначается значение 2 (HEADERS_RECEIVED). После загрузки содержимого ответа HTTP свойству readyState объекта XHR должно быть присвоено значение 3 (Loading).

После завершения загрузки HTTP-ответа для свойства readyState объекта XHR должно быть назначено значение 4 (Done). Слушатель будет реагировать только на изменения состояния, которые возникают после его определения. Чтобы обнаружить состояния 1 и 2, слушатель должен быть определен до вызова open. Открытый метод должен быть применен до вызова send.

Этот метод прерывает запрос, если объект readyState объекта XHR еще не стал 4 (Done). Метод abort гарантирует, что обработчик обратного вызова не будет вызван во время асинхронного запроса. Некоторые библиотеки AJAX используют прерывание, чтобы отменить потенциальный дубликат или испорченные запросы.

XMLHttpRequest Object Methods

Method Description
new XMLHttpRequest() Creates a new XMLHttpRequest object
abort() Cancels the current request
getAllResponseHeaders() Returns header information
getResponseHeader() Returns specific header information
open(method, url, async, user, psw) Specifies the requestmethod: the request type GET or POSTurl: the file locationasync: true (asynchronous) or false (synchronous)user: optional user namepsw: optional password
send() Sends the request to the serverUsed for GET requests
send(string) Sends the request to the server.Used for POST requests
setRequestHeader() Adds a label/value pair to the header to be sent

История XMLHttpRequest

Концепция Javascript XMLHttpRequest создавалась специалистами Outlook Web Access для применения на сервере Microsoft Exchange 2000. Версии 5 и 6 не определяли идентификатор объекта XHR на своих языках сценариев, поскольку сам идентификатор Request не был стандартным на момент выпуска. Microsoft добавила идентификатор объекта на свои языки сценариев в Internet Explorer 7.0, выпущенный в октябре 2006 года. В проекте браузера был разработан и реализован интерфейс Javascript XMLHttpRequest в механизм компоновки Gecko.

Он был смоделирован таким образом, чтобы максимально быть похожим на интерфейс Microsoft Request. Mozilla создал оболочку для использования этого интерфейса через объект JS, который был назван XMLHttpRequest. Объект уже сделали доступным в Gecko версии 0.6, выпущенной 6 декабря 2000 года, но он еще не был полностью функциональным до тех пор, пока 5 июня 2002 года не вышла версия 1.0 Gecko, после чего идентификатор объекта стал стандартом де-факто в других крупных веб-системах:

  • Safari 1.2, выпущенном в феврале 2004 года.
  • Opera 8.0, выпущенном в апреле 2005 года.
  • iCab 3.0b352, выпущенном в сентябре 2005 года.

С появлением кросс-браузерных библиотек JavaScript, таких как jQuery, разработчики могут вызывать функциональность Javascript XMLHttpRequest без кодирования непосредственно в API. Wide Web Consortium World опубликовал проект спецификации для XMLHttpRequest 5 апреля 2006 года с целью документации минимального набора совместимых функций на основе существующих реализаций, позволяя разработчикам использовать их без кода, специфичного для платформы.

25 февраля 2008 года W3C также опубликовал еще одну спецификацию рабочего проекта — XMLHttpRequest Level 2. Уровень 2 состоит из расширенной функциональности, включая поддержку для запросов и обработку байтовых потоков.

Доступные команды

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

  • alert (message) — отобразить предупреждение JavaScript.
  • setvalue (target, value) — установить значение поля формы с идентификатором из мишени.
  • setdefault (target) — сбросить значение поля формы.
  • focus (target) – установить фокус в поле формы.
  • setcontent (target, content) — установить внутренний HTML элемента HTML.
  • setstyle (target, property, value) — задать стиль элемента HTML.
  • setproperty (target, property, value) — задать свойство элемента HTML.

В каждом случае цель — это идентификатор, ссылающийся на элемент HTML-страницы. Другими значениями являются текст или HTML для добавления дополнительных параметров функции processReqChange.

JS Tutorial

JS HOMEJS IntroductionJS Where ToJS OutputJS StatementsJS SyntaxJS CommentsJS VariablesJS LetJS ConstJS OperatorsJS ArithmeticJS AssignmentJS Data TypesJS FunctionsJS ObjectsJS EventsJS StringsJS String MethodsJS String SearchJS String TemplatesJS NumbersJS Number MethodsJS ArraysJS Array MethodsJS Array SortJS Array IterationJS Array ConstJS DatesJS Date FormatsJS Date Get MethodsJS Date Set MethodsJS MathJS RandomJS BooleansJS ComparisonsJS ConditionsJS SwitchJS Loop ForJS Loop For InJS Loop For OfJS Loop WhileJS BreakJS IterablesJS SetsJS MapsJS TypeofJS Type ConversionJS BitwiseJS RegExpJS ErrorsJS ScopeJS HoistingJS Strict ModeJS this KeywordJS Arrow FunctionJS ClassesJS JSONJS DebuggingJS Style GuideJS Best PracticesJS MistakesJS PerformanceJS Reserved Words

открытый метод

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

  • Метод параметра определяет тип запроса, например методы GET, POST и т. Д., И не учитывает регистр.
  • Параметр url определяет запрашиваемый URL-адрес.
  • Параметр async определяет, обрабатывать ли запрос асинхронно, true (асинхронно) или false (синхронно), по умолчанию — true
  • Параметр username определяет имя пользователя, которое обычно не используется, по умолчанию — null.
  • Параметр password определяет пароль, обычно не используется, по умолчанию — null.

Основы

XMLHttpRequest имеет два режима работы: синхронный и асинхронный.

Сначала рассмотрим асинхронный, так как в большинстве случаев используется именно он.

Чтобы сделать запрос, нам нужно выполнить три шага:

  1. Создать .

  2. Инициализировать его.

    Этот метод обычно вызывается сразу после . В него передаются основные параметры запроса:

    • – HTTP-метод. Обычно это или .
    • – URL, куда отправляется запрос: строка, может быть и объект URL.
    • – если указать , тогда запрос будет выполнен синхронно, это мы рассмотрим чуть позже.
    • , – логин и пароль для базовой HTTP-авторизации (если требуется).

    Заметим, что вызов , вопреки своему названию, не открывает соединение. Он лишь конфигурирует запрос, но непосредственно отсылается запрос только лишь после вызова .

  3. Послать запрос.

    Этот метод устанавливает соединение и отсылает запрос к серверу. Необязательный параметр содержит тело запроса.

    Некоторые типы запросов, такие как , не имеют тела. А некоторые, как, например, , используют , чтобы отправлять данные на сервер. Мы позже увидим примеры.

  4. Слушать события на , чтобы получить ответ.

    Три наиболее используемых события:

    • – происходит, когда получен какой-либо ответ, включая ответы с HTTP-ошибкой, например 404.
    • – когда запрос не может быть выполнен, например, нет соединения или невалидный URL.
    • – происходит периодически во время загрузки ответа, сообщает о прогрессе.

Вот полный пример. Код ниже загружает с сервера и сообщает о прогрессе:

После ответа сервера мы можем получить результат запроса в следующих свойствах :

Код состояния HTTP (число): , , и так далее, может быть в случае, если ошибка не связана с HTTP.
Сообщение о состоянии ответа HTTP (строка): обычно для , для , для , и так далее.
(в старом коде может встречаться как )
Тело ответа сервера.

Мы можем также указать таймаут – промежуток времени, который мы готовы ждать ответ:

Если запрос не успевает выполниться в установленное время, то он прерывается, и происходит событие .

URL с параметрами

Чтобы добавить к URL параметры, вида , и корректно закодировать их, можно использовать объект URL:

Using XMLHttpRequest from JavaScript modules / XPCOM components

Instantiating from a JavaScript module or an XPCOM component works a little differently; it can’t be instantiated using the constructor. The constructor is not defined inside components and the code results in an error. You’ll need to create and use it using a different syntax.

Instead of this:

var req = new XMLHttpRequest();
req.onprogress = onProgress;
req.onload = onLoad;
req.onerror = onError;
req.open("GET", url, true);
req.send(null);

Do this:

var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                    .createInstance(Components.interfaces.nsIXMLHttpRequest);
req.onprogress = onProgress;
req.onload = onLoad;
req.onerror = onError;
req.open("GET", url, true);
req.send(null);

For C++ code you would need to the component to an in order to add event listeners, but chances are in C++ using a channel directly would be better.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector