Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

XMLHttpRequest

XMLHttpRequest — это объект JavaScript, созданный Microsoft и адаптированный Mozilla. Вы можете использовать его для простой передачи данных через HTTP. Несмотря на свое название, он может быть использован не только для XML документов, но и, например, для JSON.

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

В Gecko этот объект реализует интерфейсы nsIJSXMLHttpRequest и nsIXMLHttpRequest. Недавние версии Gecko содержат некоторые изменения для этого объекта (см. XMLHttpRequest changes for Gecko1.8).

Основы использования

Использовать XMLHttpRequest очень просто. Вы создаёте экземпляр объекта, открываете URL и отправляете запрос. Статус HTTP-ответа, так же как и возвращаемый документ, доступны в свойствах объекта запроса.

Замечание: Версии Firefox до версии 3 постоянно отправляют запрос, используя кодировку UTF-8. Отправляя документ, Firefox 3 использует кодировку, определенную в data.inputEncoding (где data — ненулевой объект, переданный в send()). Если не определено, то используется UTF-8.

Пример

var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', false); 
req.send(null);
if(req.status == 200)
  dump(req.responseText);
Замечание: Этот пример работает синхронно, то есть он заблокирует интерфейс пользователя, если вы вызовете его из своего кода. Не рекомендуется использовать это на практике.

Пример без http протокола

var req = new XMLHttpRequest();
req.open('GET', 'file:///home/user/file.json', false); 
req.send(null);
if(req.status == 0)
  dump(req.responseText);
Замечание: file:/// и ftp:// не возвращают HTTP статуса, вот почему они возвращают ноль в status и пустую строчку в statusText. См. баг 331610 для подробной информации.

Асинхронное использование

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

Пример

var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', true); /* Третий аргумент true означает асинхронность */
req.onreadystatechange = function (aEvt) {
  if (req.readyState == 4) {
     if(req.status == 200)
      dump(req.responseText);
     else
      dump("Error loading page\n");
  }
};
req.send(null); 

Наблюдение за прогрессом

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

Если к примеру вы желаете предоставить информацию пользователю о прогрессе получения документа, вы можете использовать код вроде этого:

function onProgress(e) {
  var percentComplete = (e.position / e.totalSize)*100;
  ...
}

function onError(e) {
  alert("Error " + e.target.status + " occurred while receiving the document.");
}

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

Атрибуты события onprogress: position и totalSize, отображают соотвественно текущие количество принятых байтов и количество ожидаемых байтов.

Все эти события имеют свои target атрибуты установленные в соответствии с XMLHttpRequest.

Замечание: Firefox 3 по сути обеспечивает установку значений-ссылок полей target, currentTarget и this у объекта события на правильные объекты во время вызова обработчика событий для XML документов представленных в XMLDocument. См. баг 198595 для деталей.

Другие Свойства и Методы

В дополнение к свойствам и методам описанным выше, ниже следуют другие полезные свойства и методы для объекта запроса.

responseXML

Если вы загрузили XML документ свойство responseXML будет содержать документ в виде XmlDocument объекта которым вы можете манипулировать используя DOM методы. Если сервер отправляет правильно сформированные XML документы но не устанавливает Content-Type заголовок для него, вы можете использовать overrideMimeType() для того чтобы документ был обработан как XML. Если сервер не отправляет правильно сформированного документа XML, responseXML вернет null независимо от любых перезаписей Content-Type заголовка.

overrideMimeType()

Этот метод может быть использован для обработки документа особенным образом. Обычно вы будете использовать его, когда запросите responseXML, и сервер отправит вам XML, но не отправит правильного Content-Type заголовка.

Замечание: Этот метод должен вызываться до вызова send().
var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', true);
req.overrideMimeType('text/xml');
req.send(null);

setRequestHeader()

Этот метод может быть использован чтобы установить HTTP заголовок в запросе до его отправки.

Замечание: Вы должны вызвать вначале open().
var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', true);
req.setRequestHeader("X-Foo", "Bar");
req.send(null);

getResponseHeader()

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

var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', false);
req.send(null);
dump("Content-Type: " + req.getResponseHeader("Content-Type") + "\n");

abort()

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

var req = new XMLHttpRequest();
req.open('GET', 'https://www.mozilla.org/', false);
req.send(null);
req.abort();

mozBackgroundRequest

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

var req = new XMLHttpRequest();
req.mozBackgroundRequest = true;
req.open('GET', 'https://www.mozilla.org/', true);
req.send(null);

Using from XPCOM components

Note: Changes are required if you use XMLHttpRequest from a JavaScript XPCOM component.

XMLHttpRequest cannot be instantiated using the XMLHttpRequest() constructor from a JavaScript XPCOM component. 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 QueryInterface the component to an nsIEventTarget in order to add event listeners, but chances are in C++ using a channel directly would be better.

Limited number of simultaneous XMLHttpRequest connections

The about:config preference: network.http.max-persistent-connections-per-server limits the number of connections. In Firefox 3 this value is 6 by default, previous versions use 2 as the default. Some interactive web pages using xmlHttpRequest may keep a connection open. Opening two or three of these pages in different tabs or on different windows may cause the browser to hang in such a way that the window no longer repaints and browser controls don't respond.

Binary Content

Although less typical than sending/receiving character-oriented content, XMLHttpRequest can be used to send and receive binary content.

Retrieving binary content

// Fetches BINARY FILES synchronously using XMLHttpRequest
function load_binary_resource(url) {
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
  //XHR binary charset opt by Marcus Granado 2006 [https://mgran.blogspot.com]
  req.overrideMimeType('text/plain; charset=x-user-defined');
  req.send(null);
  if (req.status != 200) return '';
  return req.responseText;
}

var filestream = load_binary_resource(url);
// x is the offset (i.e. position) of the byte in the returned binary file stream. The valid range for x is from 0 up to filestream.length-1.
var abyte = filestream.charCodeAt(x) & 0xff; // throw away high-order byte (f7)

See downloading binary streams with XMLHttpRequest for a detailed explanation. See also downloading files.

Sending binary content

This example POSTs binary content asynchronously. aBody is some data to send.

 var req = new XMLHttpRequest();
 req.open("POST", url, true);
 // set headers and mime-type appropriately
 req.setRequestHeader("Content-Length", 741);
 req.sendAsBinary(aBody);

You can also send binary content by passing an instance of interface nsIFileInputStream to req.send(). In that case, there is not need to set the Content-Length request header:

// Make a stream from a file. The file variable holds an nsIFile
var stream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                       .createInstance(Components.interfaces.nsIFileInputStream);
stream.init(file, 0x04 | 0x08, 0644, 0x04); // file is an nsIFile instance   

// Try to determine the MIME type of the file
var mimeType = "text/plain";
try {
  var mimeService = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsIMIMEService);
  mimeType = mimeService.getTypeFromFile(file); // file is an nsIFile instance
}
catch(e) { /* eat it; just use text/plain */ }

// Send    
var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                    .createInstance(Components.interfaces.nsIXMLHttpRequest);
req.open('PUT', url, false); /* synchronous! */
req.setRequestHeader('Content-Type', mimeType);
req.send(stream);

Bypassing cache

Normally, XMLHttpRequest attempts to retrieve content from local cache. To bypass this attempt, do the following:

 var req = new XMLHttpRequest();
 req.open('GET', url, false);
 req.channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
 req.send(null);

An alternative approach to bypassing cache, as described here:

 var req = new XMLHttpRequest();
 req.open("GET", url += (url.match(/\?/) == null ? "?" : "&") + (new Date()).getTime(), false);
 req.send(null);

This appends a timestamp URL parameter to the URL, taking care to insert a ? or & as appropriate. For example, https://foo.com/bar.html becomes https://foo.com/bar.html?12345 and https://foo.com/bar.html?foobar=baz becomes https://foo.com/bar.html?foobar=baz&12345. Since local cache is indexed by URL, the idea is that every URL used by XMLHttpRequest is unique, bypassing the cache.

Downloading JSON and JavaScript in extensions

Extensions shouldn't use eval() on JSON or JavaScript downloaded from the web. See Downloading JSON and JavaScript in extensions for details.

References

  1. MDC AJAX introduction
  2. XMLHttpRequest - REST and the Rich User Experience
  3. XULPlanet documentation
  4. Microsoft documentation
  5. Apple developers' reference
  6. "Using the XMLHttpRequest Object" (jibbering.com)
  7. The XMLHttpRequest Object: W3C Working Draft

Метки документа и участники

Метки: 
 Внесли вклад в эту страницу: denpatin, dehero, teoli, torbasow, TotalAMD, shergin, Bzbarsky, Atzkey, Apparition
 Обновлялась последний раз: denpatin,