Xmlhttprequest.response

Более сложный пример

Чтобы завершить статью, мы рассмотрим несколько более сложный пример, который показывает более интересные применения Fetch. Мы создали образец сайта под названием The Can Store — это вымышленный супермаркет, который продаёт только консервы. Вы можете найти этот пример в прямом эфире на GitHub и посмотреть исходный код.

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

Существует довольно много сложного кода, который включает фильтрацию продуктов по категориям и поисковым запросам, манипулирование строками, чтобы данные отображались правильно в пользовательском интерфейсе и т.д. Мы не будем обсуждать все это в статье, но вы можете найти обширные комментарии в коде (см. can-script.js).

Однако мы объясним код Fetch.

Первый блок, который использует Fetch, можно найти в начале JavaScript:

Это похоже на то, что мы видели раньше, за исключением того, что второй промис находится в условном выражении. В этом случае мы проверяем, был ли возвращённый ответ успешным — свойство (en-US) содержит логическое значение, которое , если ответ был в порядке (например, 200 meaning «OK») или , если он не увенчался успехом.

Если ответ был успешным, мы выполняем второй промис — на этот раз мы используем (en-US), а не (en-US), так как мы хотим вернуть наш ответ как структурированные данные JSON, а не обычный текст.

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

Вы можете проверить сам случай отказа:

  1. Создание локальной копии файлов примеров (загрузка и распаковка the can-store ZIP file)
  2. Запустите код через веб-сервер (как описано выше, в )
  3. Измените путь к извлечённому файлу, например, «product.json» (т.е. убедитесь, что он написан неправильно)
  4. Теперь загрузите индексный файл в свой браузер (например, через ) и посмотрите в консоли разработчика браузера. Вы увидите сообщение в строке «Запрос сети для продуктов.json не удалось с ответом 404: Файл не найден»

Второй блок Fetch можно найти внутри функции :

Это работает во многом так же, как и предыдущий, за исключением того, что вместо использования (en-US) мы используем (en-US) — в этом случае мы хотим вернуть наш ответ в виде файла изображения, а формат данных, который мы используем для этого — Blob — этот термин является аббревиатурой от« Binary Large Object »и может в основном использоваться для представляют собой большие файловые объекты, такие как изображения или видеофайлы.

После того как мы успешно получили наш blob, мы создаём URL-адрес объекта, используя . Это возвращает временный внутренний URL-адрес, указывающий на объект, указанный в браузере. Они не очень читаемы, но вы можете видеть, как выглядит, открывая приложение Can Store, Ctrl-/щёлкнуть правой кнопкой мыши по изображению и выбрать опцию «Просмотр изображения» (которая может немного отличаться в зависимости от того, какой браузер вы ). URL-адрес объекта будет отображаться внутри адресной строки и должен выглядеть примерно так:

blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4

Мы хотели бы, чтобы вы решили преобразовать версию приложения Fetch для использования XHR в качестве полезной части практики. Возьмите копию ZIP файла и попробуйте изменить JavaScript, если это необходимо.

Некоторые полезные советы:

  • Вы можете найти полезный справочный материал .
  • Вам в основном нужно использовать тот же шаблон, что и раньше, в примере XHR-basic.html.
  • Однако вам нужно будет добавить обработку ошибок, которые мы показали вам в версии Fetch Can Store:
    • Ответ найден в после того, как событие запущено, а не в промисе .
    • О наилучшем эквиваленте Fetch’s в XHR следует проверить, является ли равным 200 или если равно 4.
    • Свойства для получения статуса и сообщения состояния одинаковы, но они находятся на объекте (XHR), а не в объекте .

Примечание: Если у вас есть проблемы с этим, не стесняйтесь сравнить свой код с готовой версией на GitHub (см. исходник здесь, а также см. это в действии).

Частые проблемы¶

Кеширование

Многие браузеры поддерживают кеширование ответов на XmlHttpRequest запросы. При этом реализации кеширования немного разные.

Например, при повторном XmlHttpRequest на тот же URL, Firefox посылает запрос с заголовком «» со значением, указанным в заголовке «» предыдущего ответа.

А Internet Explorer делает так, только когда кешированный ответ устарел, т. е. после времени из заголовка «Expires» предыдущего ответа. Поэтому, кстати, многие думают, что Internet Explorer вообще не очищает кеш ответов.

Самое простое решение проблемы — просто убрать кеширование. Например, при помощи заголовков, или добавлением случайного параметра в URL типа:

Есть, однако, ряд случаев, когда кеширование XMLHttpRequest браузером полезно, улучшает время ответа и экономит трафик.

Пример демонстрирует универсальный код работы с кешем для Internet Explorer и Firefox.

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

Ссылку на кешированый запрос сохраняем, т. к. если код ответа дополнительного запроса — «», то его тело станет пустой строкой («»), и нужно будет вернуться к кешированному объекту. Более эффективным, впрочем, будет не создавать новый объект , а сохранить данные из существующего и использовать заново его же.

Пример выше опирается на то, что сервер всегда выдает заголовок «», что верно для большинства конфигураций. В нем делается синхронный запрос. В асинхронном случае, проверка на Date и т. д. нужно делать после получения ответа в функции-обработчике .

Повторное использование объекта XmlHttpRequest

В Internet Explorer, если вызван после установки , может быть проблема с повторным использованием этого XmlHttpRequest.

Чтобы использовать заново XmlHttpRequest, сначала вызывайте метод , а затем — присваивайте . Это нужно потому, что IE неявно очищает объект XmlHttpRequest в методе , если его статус «».

Вызывать для перенаправления запроса на другой URL не нужно, даже если текущий запрос еще не завершился.

Утечки памяти

В Internet Explorer объект XmlHttpRequest принадлежит миру DOM/COM, а Javascript-функция — миру Javascript. Вызов r неявную круговую связь: ссылается на функцию через , а функция, через область видимости — видит (ссылается на) .

Невозможность обнаружить и оборвать такую связь во многих (до IE 6,7 редакции июня 2007?) версиях Internet Explorer приводит к тому, что XmlHttpRequest вместе с ответом сервера, функция-обработчик, и всё замыкание прочно оседают в памяти до перезагрузки браузера.

Чтобы этого избежать, ряд фреймворков (YUI, dojo…) вообще не ставят , а вместо этого через проверяют его каждые 10 миллисекунд. Это разрывает круговую связку <-> , и утечка памяти не грозит даже в самых глючных браузерах.

Bugs and inconsistencies[edit | edit source]

Dealing with bugs and inconsistencies in XMLHttpRequest implementations:

Cachingedit | edit source

Most of the implementations also realize HTTP caching. Internet Explorer and Firefox do, but there is a difference in how and when the cached data is revalidated.
Firefox revalidates the cached response every time the page is refreshed, issuing an «If-Modified-Since» header with value set to the value of the «Last-Modified» header of the cached response.

Internet Explorer does so only if the cached response is expired (i.e., after the date of received «Expires» header). This raises some issues, since a bug exists in Internet Explorer, where the cached response is never refreshed.

It is possible to unify the caching behavior on the client. The following script illustrates an example approach:

var request = new XMLHttpRequest();
request.open("GET", url, false);
request.send(null);
if (!request.getResponseHeader("Date")) {
  var cached = request;
  request = new XMLHttpRequest();
  var ifModifiedSince =
  cached.getResponseHeader("Last-Modified") ||
  new Date(); // January 1, 1970
  request.open("GET", url, false);
  request.setRequestHeader("If-Modified-Since", ifModifiedSince);
  request.send("");
  if (request.status == 304) {
    request = cached;
  }
}

In Internet Explorer, if the response is returned from the cache without revalidation, the «Date» header is an empty string. The workaround is achieved by checking the «Date» response header and issuing another request if needed. In case a second request is needed, the actual HTTP request is not made twice, as the first call would not produce an actual HTTP request.

The reference to the cached request is preserved, because if the response code/status of the second call is «304 Not Modified», the response body becomes an empty string («») and then it is needed to go back to the cached object. A way to save memory and expenses of second object creation is to preserve just the needed response data and reuse the XMLHttpRequest object.

The above script relies on the assumption that the «Date» header is always issued by the server, which should be true for most server configurations. Also, it illustrates a synchronous communication between the server and the client. In case of asynchronous communication, the check should be made during the callback.

This problem is often overcome by employing techniques preventing the caching at all. Using these techniques indiscriminately can result in poor performance and waste of network bandwidth.

If script executes operation that has side effects (e.g. adding a comment, marking message as read) which requires that request always reaches the end server, it should use POST method instead.

Workaroundedit | edit source

Internet Explorer will also cache dynamic pages and this is a problem because the URL of the page may not change but the content will (for example a news feed). A workaround for this situation can be achieved by adding a unique time stamp or random number, or possibly both, typically using the Date object and/or Math.random().

For simple document request the query string delimiter ‘?’ can be used, or for existing queries a final sub-query can be added after a final ‘&’ – to append the unique query term to the existing query. The downside is that each such request will fill up the cache with useless (never reused) content that could otherwise be used for other cached content (more useful data will be purged from cache to make room for these one-time responses).

A better workaround can be achieved by adding meta tags to dynamic pages in order to make them no-cachable:

<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />

Использование 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)
  ...
}

基本

XMLHttpRequest には2つの操作モードがあります: 同期と非同期です。

先に、ほとんどのケースで使われる非同期を見ていきましょう。

リクエストをするためには、次の3ステップが必要です:

  1. を作成します:

  2. 初期化をします:

    このメソッドは通常 のすぐ後で呼ばれ、リクエストのメインのパラメータを指定します。:

    • – HTTPメソッド. たいてい か です.
    • – リクエストURL。文字列で、URL オブジェクトもOKです。
    • – 明示的に が指定されている場合、リクエストは同期になります。これについては後ほど説明します。
    • , – ベーシック HTTP 認証のユーザとパスワードです(必要に応じて).

    呼び出しに注意してください。その名前とは対照的に、接続をオープンするわけではありません。リクエストを設定するだけで、ネットワーク処理は 呼び出しでのみ始まります。

  3. それを送ります

    このメソッドは接続をオープンし、リクエストをサーバに送信します。オプションの パラメータにはリクエストボディが含まれます。

    のようないくつかのリクエストメソッドは body を持ちません。また などはデータをサーバに送信するのに を使います。後ほど例を見ていきます。

  4. 応答に対するイベントをリッスンします

    これら3つがもっとも広く使われています:

    • – 結果が準備できたとき。404 のような HTTP エラーを含みます。
    • – リクエストが送信できなかったとき e.g. ネットワークダウン or URL不正
    • – ダウンロード中に定期的にトリガーされ、ダウンロードされた量が確認できます。

これは完全な例です。下のコードはサーバから のURLをロードし、進行状況を表示します。:

サーバーが応答すると、リクエストオブジェクトの次のプロパティで結果を受け取ることができます。:

HTTPステータスコード(数値): , , など。HTTP 以外の失敗の場合は になります。

:HTTPステータスメッセージ(文字列): 通常, の場合は 、 の場合は 、 の場合は など。

(古いスクリプトはを使用する場合があります)
:サーバーのレスポンス。

対応するプロパティを使用してタイムアウトを指定することもできます。:

リクエストが指定時間内で成功しない場合はキャンセルされ、 イベントが発生します。

URL 検索パラメータ

のような URL パラメータを渡しつつ、適切なエンコーディングを保証するには、URL オブジェクトが使えます。:

Analizando y Manipulando el Texto de Respuesta HTML

Si usas HTML remota, el (texto de la respuesta) sera una cadena que contenga una «sopa» de etiquetas HTML, lo que puede ser dificil de analizar y manipular. Existen tres maneras principales de analizar estas cadenas HTML

  1. repidamente convertira la cadena HTML en DOM, al mismo tiempo que tira javascript y otros elementos avanzados, incluyendo la etiqueta de la página.
  2. RegExp se puede usar si de antemano conoces el HTML que vendra en el . Quizas quieras remover los saltos de linea, si usas RegExp para escanear considerandolos. Sin embargo, este metodo es un «ultimo recurso» ya que si el HTML cambia ligeramente, posiblemente fallara.
  3. para cargar toda la pagina también se puede hacer para manipularla luego como DOM, sin embargo existen riesgos de seguridad al dar a código remoto este nivel de acceso privilegiado, que puede causar problemas en la revisión de tu addon. Por ejemplo, si una pagina ejecuta el comando común «» para cargar, esto se interpretara como cambiar la locación del navegador ( en una extensión) en contraposición a la locación de una página web ( en una extensión), y en consecuecia destruir todos los componentes del navegador. Alternativamente, y de algun modo mas seguro, una cadena RegExp para remover problemas de javascript, luego cargada en un iframe oculto previamente  establecido:
document.getElementById('hiddenXULiframe').contentWindow.document.body.innerHTML = req.responseText

Создание асинхронных запросов с помощью XHR

Что такое асинхронный запрос, мы уже разобрали выше. Т.е. это такой, который выполняется в фоне и не мешает пользователю взаимодействовать со страницей.

А это значит, что при отправке такого запроса, страница не «замораживается», с ней можно работать дальше.

– это аббревиатура от объекта , позволяющего взаимодействовать с сервером.

1. Начинается написания запроса с создания экземпляра объекта :

const xhr = new XMLHttpRequest();

2. После этого следует инициализировать запрос с помощью метода :

xhr.open(method, url]]);

Где:

  • – метод отправки запроса на сервер (, , , , );
  • – URL для отправки запроса;
  • – определяет, как следует выполнять запрос: асинхронно ( – по умолчанию) или нет ();
  • и – имя пользователя и пароль, использующиеся для аутентификации (по умолчанию имеют значение ).

Например:

// GET – метод, по которому будем делать запрос
// requestURL – переменная, содержащая URL для отправки запроса
xhr.open('GET', requestURL);

3. Следующий шаг – это назначить обработчик на событие объекта :

xhr.onreadystatechange = function() {
  // ...
}

Это событие происходит при изменении статуса запроса .

– это свойство, содержащее числовой код, по которому можно определить в какой сейчас стадии находится запрос.

Статусы кодов :

  • 0 – создан объект , но метод ещё не вызывался;
  • 1 – открыто новое соединение с помощью (этот этап также включает установку значений HTTP заголовкам с помощью );
  • 2 – отправлен (вызван и получены заголовки ответа);
  • 3 – получена часть ответа;
  • 4 – завершён.

Из всех этих статусов нам интересен только 4. Он будет означать, что ответ от сервера получен и его можно обработать. Остальные коды на практике практически не используются.

Таким образом напишем проверку на равенство значения числу 4:

xhr.onreadystatechange = function() {
  if (xhr.readyState !== 4) {
    return;
  }
  // все в порядке, ответ получен
}

Следующее, что нужно проверить – это статус HTTP-ответа. Он находится в свойстве .

Если запрос был успешно выполнен сервером, то его статус будет 200. Другие ответы нам в большинстве случаев не интересны. Например, если равен 404 (запрашиваемый URL не найден), то в этом случае запрашиваемых данных нет и мы можем только как-то обработать это ошибку.

Добавим ещё одно условие в код: проверку на равенство 200.

xhr.onreadystatechange = function() {
  if (xhr.readyState !== 4 && xhr.status !== 200) {
    return;
  }
  // все в порядке, ответ получен и его статус равен 200
}

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

Получить данные (ответ от сервера) можно в виде строки () или объекта XML Document ().

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

xhr.onreadystatechange = function() {
  if (xhr.readyState !== 4 || xhr.status !== 200) {
    return;
  }
  const response = xhr.responseText;
  console.log(response);
}

4. Последний этап – это отправка запроса. Выполняется это с помощью метода .

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

В при необходимости можно передать аргумент (данные серверу в теле запроса). Если это не сделать, то по умолчанию будет использоваться значение .

Запросы GET создаются без тела, все параметры, которые нужно передать серверу здесь указывается в самом URL. Поэтому чтобы тело запроса было пустое, как уже было отмечено выше, нужно вызвать метод без аргументов или с аргументом .

Отправим запрос:

xhr.send();

Итоговый код:

const xhr = new XMLHttpRequest();
xhr.open('GET', requestURL);
xhr.onreadystatechange = function() {
  if (xhr.readyState !== 4 || xhr.status !== 200) {
    return;
  }
  const response = xhr.responseText;
  console.log(response);
}
xhr.send();

サマリ

を使用した GET リクエストの典型的なコード:

実施にはより多くのイベントがあり、 でリストされています(ライフサイクル順):

  • – リクエストが開始された
  • – レスポンスのデータパケットが到着し、その時点のレスポンス本文全体は にあります
  • – リクエストが 呼び出しによりキャンセルされた
  • – 接続エラーが発生。e.g. 間違ったドメイン名など. 404 などのHTTPエラーでは発生しません。
  • – リクエストが正常に終了した
  • – タイムアウトでリクエストがキャンセルされた(タイムアウトが設定された場合のみ)).
  • – , , or の後に発生します。.

, , , と イベントは相互に排他的です。それらの1つだけが発生します。

最も使われているイベントはロード完了 (), ロード失敗()です。あるいは、単一の ハンドラを使用して何が起こったのかを確認するためにレスポンスをチェックします。

すでに別のイベント を見てきました。歴史的には、仕様が定まるずっと前からありました。最近では、これを使う必要はありません。新しいイベントに置き換えることができますが、多くの場合、古いスクリプトにあります。

特にアップロードを追跡する必要がある場合は、 オブジェクトで同じイベントをリッスンする必要があります。

Notes

  • By default, Firefox 3 limits the number of connections per server to 6 (previous versions limit this to 2 per server). Some interactive web sites may keep an connection open, so opening multiple sessions to such sites may result in the browser hanging in such a way that the window no longer repaints and controls don’t respond. This value can be changed by editing the preference in .
  • From Gecko 7.0 headers set by are sent with the request when following a redirect. Previously these headers would not be sent.
  • is implemented in Gecko using the , , and interfaces.
  • When a request reaches its timeout value, a «timeout» event is raised.

Events

as a property of the instance is supported in all browsers.

Since then, a number of additional event handlers were implemented in various browsers (, , , etc.). These are supported in Firefox. In particular, see and Using XMLHttpRequest.

More recent browsers, including Firefox, also support listening to the events via standard APIs in addition to setting properties to a handler function.

Синхронные запросы

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

Другими словами, выполнение JavaScript останавливается на и возобновляется после получения ответа. Так ведут себя, например, функции или .

Вот переписанный пример с параметром , равным :

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

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

Из-за всего этого синхронные запросы используют очень редко. Мы более не будем рассматривать их.

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.

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.

HTTP ヘッダ

はカスタムヘッダの送信とレスポンスからのヘッダ読み取り、両方が可能です。

HTTP ヘッダに関しては3つのメソッドがあります。:

指定された と のリクエストヘッダを設定します。

例:

ヘッダの制限

いくつかのヘッダはブラウザだけが管理しています。例えば、 や です。
完全なリストは にあります。

ユーザの安全性やリクエストの正当性の観点から、 ではそれらを変更することは許可されていません。 «`

ヘッダを削除することはできません

のもう一つの特徴は を取り消すことはできないということです。

一度ヘッダを設定すると、それが設定されます。さらなる呼び出しはヘッダへの情報の追加であり、上書きでは有りません。

例:

指定された ( と は除く) のレスポンスヘッダを取得します。

例:

と を除く、すべてのレスポンスヘッダを返します。

ヘッダは次のように1行で返却されます。:

ヘッダ間の改行は常に です(OSに依存しません)。なので、簡単に個々のヘッダに分割することができます。名前と値のセパレータは常にコロンとそれに続くスペースです 。これは仕様で決められています。

なので、name/value のペアをもつオブジェクトを取得したい場合は少し JS が必要になります。

例えばこのようになります(2つのヘッダの名前が同じ場合、前者のヘッダが後者のヘッダで上書きされる想定です):

Summary

Typical code of the GET-request with :

There are actually more events, the lists them (in the lifecycle order):

  • – the request has started.
  • – a data packet of the response has arrived, the whole response body at the moment is in .
  • – the request was canceled by the call .
  • – connection error has occurred, e.g. wrong domain name. Doesn’t happen for HTTP-errors like 404.
  • – the request has finished successfully.
  • – the request was canceled due to timeout (only happens if it was set).
  • – triggers after , , or .

The , , , and events are mutually exclusive. Only one of them may happen.

The most used events are load completion (), load failure (), or we can use a single handler and check the properties of the request object to see what happened.

We’ve already seen another event: . Historically, it appeared long ago, before the specification settled. Nowadays, there’s no need to use it, we can replace it with newer events, but it can often be found in older scripts.

If we need to track uploading specifically, then we should listen to same events on object.

JSON Example

This example reads a menu from myTutorials.txt, and displays the menu in a web
page:

JSON Example

<div id=»id01″></div><script>var xmlhttp = new XMLHttpRequest();
var url = «myTutorials.txt»;xmlhttp.onreadystatechange = function()
{    if (this.readyState == 4 && this.status ==
200) {        var myArr = JSON.parse(this.responseText);       
myFunction(myArr);    }};xmlhttp.open(«GET», url, true);
xmlhttp.send();function myFunction(arr) {    var
out = «»;    var i;    for(i = 0; i <
arr.length; i++) {        out += ‘<a
href=»‘ + arr.url + ‘»>’ +        
arr.display + ‘</a><br>’;    }   
document.getElementById(«id01»).innerHTML = out;}
</script>

Итого

Типичный код GET-запроса с использованием :

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

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

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

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

Также мы уже видели событие: . Исторически оно появилось одним из первых, даже раньше, чем была составлена спецификация. Сегодня нет необходимости использовать его, так как оно может быть заменено современными событиями, но на него можно часто наткнуться в старом коде.

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

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

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

Adblock
detector