XMLHttpRequest

Поделись знанием:
(перенаправлено с «XHR»)
Перейти к: навигация, поиск

XMLHttpRequest (XMLHTTP, XHR) — API, доступное в скриптовых языках браузеров, таких как JavaScript. Использует запросы HTTP или HTTPS напрямую к веб-серверу и загружает данные ответа сервера напрямую в вызывающий скрипт.[1] Информация может передаваться в любом текстовом формате, например, в XML, HTML или JSON. Позволяет осуществлять HTTP-запросы к серверу без перезагрузки страницы.

XMLHTTP является важной составляющей технологии AJAX (Asynchronous JavaScript And XML), используется многими сайтами для создания динамичных, быстро реагирующих на запросы пользователя приложений. Например XMLHTTP используется такими сайтами, как Bing Maps, Gmail, Google Maps, Google Suggest, Facebook.

XMLHTTP работает только с файлами, находящимися на том же домене, что и использующая XMLHTTP страница, но существует возможность обойти ограничение. Как и в случае JavaScript, это сделано в целях безопасности (cross-site scripting).

Хотя в названии присутствует аббревиатура XML, технология не накладывает ограничений на формат передаваемых данных. Данные можно пересылать как в виде XML, так и в JSON, HTML или просто неструктурированным текстом. Разработчик может самостоятельно создать формат для передачи данных. Однако нужно учитывать, что при пересылке используется текстовый протокол HTTP и потому при использовании метода GET данные должны передаваться в виде текста (то есть бинарные данные следует кодировать, к примеру в base64). При использовании метода POST в кодировании нет необходимости.





История

Впервые был разработан компанией Microsoft, появившись в компоненте Outlook Web Access программного продукта Microsoft Exchange Server 2000. Он был назван IXMLHTTPRequest. Позднее, наработки были включены в состав MSXML 2.0 в виде объекта ActiveX, доступного через JScript, VBScript или другие скриптовые языки, поддерживающиеся браузером. MSXML 2.0 был включён в состав браузера Internet Explorer 5.

Программисты проекта Mozilla затем разработали совместимую версию, называющуюся nsIXMLHttpRequest в Mozilla 0.6. Доступ к компоненту был реализован через JavaScript-объект, названный XMLHttpRequest. Однако, полной функциональности удалось добиться только в Mozilla 1.0. В дальнейшем поддержка XMLHttpRequest появилась в браузерах Safari 1.2, Opera 8.01 и в других.

Последняя официальная спецификация — версия 1.0 ([xhr.spec.whatwg.org/ XMLHttpRequest] от 19 декабря 2012 года), которая имеет статус текущего стандарта (Living Standard) и версия 2.0 ([www.w3.org/TR/XMLHttpRequest2/ XMLHttpRequest Level 2] от 17 января 2012 года), имеющая статус рабочего варианта. Во второй версии вводятся обработчики событий прогресса, поддержка кросс-доменных запросов и работа с бинарными данными.[2]

Методы класса XMLHttpRequest

Метод Описание
abort() Отменяет текущий запрос, удаляет все заголовки, ставит текст ответа сервера в null.
getAllResponseHeaders() Возвращает полный список HTTP-заголовков в виде строки. Заголовки разделяются знаками переноса (CR+LF).
Если флаг ошибки равен true, возвращает пустую строку.
Если статус 0 или 1, вызывает ошибку INVALID_STATE_ERR.
getResponseHeader(headerName) Возвращает значение указанного заголовка.
Если флаг ошибки равен true, возвращает null.
Если заголовок не найден, возвращает null.
Если статус 0 или 1, вызывает ошибку INVALID_STATE_ERR.
open(method, URL, async, userName, password) Определяет метод, URL и другие опциональные параметры запроса;
параметр async определяет, происходит ли работа в асинхронном режиме.
Последние два параметра необязательны.
send(content) Отправляет запрос на сервер.
setRequestHeader(label, value) Добавляет HTTP-заголовок к запросу.
overrideMimeType(mimeType) Позволяет указать mime-type документа, если сервер его не передал или передал неправильно.
Внимание: метод отсутствует в Internet Explorer!

Свойства класса XMLHttpRequest

Свойство Тип Описание
onreadystatechange EventListener Обработчик события, которое происходит при каждой смене состояния объекта. Имя должно быть записано в нижнем регистре.
readyState unsigned short Текущее состояние объекта (0 — не инициализирован, 1 — открыт, 2 — отправка данных, 3 — получение данных и 4 — данные загружены)
responseText DOMString Текст ответа на запрос.
Если состояние не 3 или 4, возвращает пустую строку.
responseXML Document Текст ответа на запрос в виде XML, который затем может быть обработан посредством DOM.
Если состояние не 4, возвращает null.
status unsigned short HTTP-статус в виде числа (404 — «Not Found», 200 — «OK» и т. д.)
statusText DOMString Статус в виде строки («Not Found», «OK» и т. д.).
Если статус не распознан, браузер пользователя должен вызвать ошибку INVALID_STATE_ERR.

Ошибки, вызываемые классом XMLHttpRequest

Название Код Описание
SECURITY_ERR 18 Вызывается при попытке совершить запрос, запрещённый настройками безопасности в браузере пользователя.
NETWORK_ERR 101 Вызывается при ошибке сети (во время синхронного запроса).
ABORT_ERR 102 Вызывается при прерывании пользователем запроса (во время синхронного запроса).

Пример использования

План работы с объектом XMLHttpRequest можно представить следующим образом:

  1. Создание экземпляра объекта XMLHttpRequest
  2. Открытие соединения
  3. Установка обработчика события (нужно делать после открытия и до отправки в IE)
  4. Отправка запроса.

Создание экземпляра объекта XMLHttpRequest.

На этой стадии необходима отдельная реализация для разных браузеров. Конструкция создания объекта отличается: в IE 5 — IE 6 она реализована через ActiveXObject, а в остальных браузерах (IE 7 и выше, Mozilla, Opera, Chrome, Netscape и Safari) — как встроенный объект типа XMLHttpRequest.

Вызов для ранних версий Internet Explorer выглядит так[3]:

var req = new ActiveXObject("Microsoft.XMLHTTP");

В остальных браузерах:

var req = new XMLHttpRequest();

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

В качестве универсального решения предлагается использование такой функции:

function createRequestObject() {
  if (typeof XMLHttpRequest === 'undefined') {
    XMLHttpRequest = function() {
      try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
        catch(e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
        catch(e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP"); }
        catch(e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP"); }
        catch(e) {}
      throw new Error("This browser does not support XMLHttpRequest.");
    };
  }
  return new XMLHttpRequest();
}

Установка обработчика событий, открытие соединения и отправка запросов

Эти вызовы выглядят так:

req.open(<"GET"|"POST"|...>, <url>[, <asyncFlag>[, <user>, <password>]]);
req.onreadystatechange = processReqChange;

Где:

  • <«GET»|«POST»|…> — метод запроса. Допускаются: DELETE, GET, HEAD, OPTIONS, POST, PUT.
  • <url> — адрес запроса.
  • <asyncFlag> — флаг, определяющий, использовать ли асинхронный запрос. По умолчанию, установлен в true.
  • <user>, <password> — логин и пароль, соответственно. Указываются при необходимости.

После определения всех параметров запроса его остается только отправить. Делается это методом send(). При отправке GET-запроса для версии без ActiveX необходимо указать параметр null, в остальных случаях можно не указывать никаких параметров. Не будет ошибкой, если для GET всегда будет указан параметр null:

req.send(null);

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

var req;

function loadXMLDoc(url)
{
    req = null;
    if (window.XMLHttpRequest) {
        try {
            req = new XMLHttpRequest();
        } catch (e){}
    } else if (window.ActiveXObject) {
        try {
            req = new ActiveXObject('Msxml2.XMLHTTP');
        } catch (e){
            try {
                req = new ActiveXObject('Microsoft.XMLHTTP');
            } catch (e){}
        }
    }

    if (req) {       
        req.open("GET", url, true);
        req.onreadystatechange = processReqChange;
        req.send(null);
    }
}

function processReqChange()
{
  try { // Важно!
    // только при состоянии "complete"
    if (req.readyState == 4) {
        // для статуса "OK"
        if (req.status == 200) {
            // обработка ответа
        } else {
            alert("Не удалось получить данные:\n" +
                req.statusText);
        }
    }
  }
  catch( e ) {
      // alert('Ошибка: ' + e.description);
      // В связи с багом XMLHttpRequest в Firefox приходится отлавливать ошибку
      // Bugzilla Bug 238559 XMLHttpRequest needs a way to report networking errors
      // bugzilla.mozilla.org/show_bug.cgi?id=238559
  }
}

Известные проблемы

См. также

Напишите отзыв о статье "XMLHttpRequest"

Ссылки

  1. [www.w3.org/TR/XMLHttpRequest/ XMLHttpRequest object explained by the W3C Working Draft]. W3.org. Проверено 14 июля 2009. [www.webcitation.org/65Ddtuvhv Архивировано из первоисточника 5 февраля 2012].
  2. [habrahabr.ru/post/120917/ Новые возможности XMLHttpRequest2]
  3. [blogs.msdn.com/ie/archive/2006/01/23/516393.aspx Native XMLHTTPRequest object]

История

  • [www.alexhopmann.com/xmlhttp.htm История XMLHTTP глазами одного из разработчиков]  (англ.)

Реализация в браузерах

  • [developer.apple.com/internet/webcontent/xmlhttpreq.html Apple Safari] и KDE [developer.kde.org/documentation/library/cvs-api/kdelibs-apidocs/khtml/html/xmlhttprequest_8h-source.html Konqueror]
  • [msdn.microsoft.com/en-us/library/ms759148(VS.85).aspx Microsoft IXMLHTTPRequest]
  • [developer.mozilla.org/en/nsIXMLHttpRequest Mozilla nsIXMLHttpRequest]
  • [developer.mozilla.org/en/docs/AJAX:Getting_Started Mozilla XMLHttpRequest object HowTo]
  • [www.mozilla.org/xmlextras/ Mozilla XML Extras]
  • Opera [www.opera.com/docs/specs/opera9/index.dml для компьютеров] и [www.opera.com/pressreleases/en/2005/11/15/index.dml для мобильных телефонов]

Учебные руководства

  • [xmlhttprequest.ru XMLHTTPRequest: описание, применение, частые проблемы]
  • [www.webmascon.com/topics/technologies/13a.asp Сверхдинамичные веб-интерфейсы]

Стандарты

  • [www.w3.org/TR/XMLHttpRequest Создана рабочая группа по стандартизации XMLHTTPRequest во всех браузерах]

Литература

  • Дейв Крейн, Эрик Паскарелло, Даррен Джеймс. AJAX в действии: технология - Asynchronous JavaScript and XML = Ajax in Action. — М.: «Вильямс», 2006. — С. 640. — ISBN 1-932394-61-3.
  • Дари К., Бринзаре Б., Черчез-Тоза Ф., Бусика М. AJAX и PHP: разработка динамических веб-приложений. — СПб.: Символ Плюс, 2006. — С. 336. — ISBN 5-93286-077-4.

Отрывок, характеризующий XMLHttpRequest

– Уж как просили, ваше благородие, – сказал старый солдат с дрожанием нижней челюсти. – Еще утром кончился. Ведь тоже люди, а не собаки…
– Сейчас пришлю, уберут, уберут, – поспешно сказал фельдшер. – Пожалуйте, ваше благородие.
– Пойдем, пойдем, – поспешно сказал Ростов, и опустив глаза, и сжавшись, стараясь пройти незамеченным сквозь строй этих укоризненных и завистливых глаз, устремленных на него, он вышел из комнаты.


Пройдя коридор, фельдшер ввел Ростова в офицерские палаты, состоявшие из трех, с растворенными дверями, комнат. В комнатах этих были кровати; раненые и больные офицеры лежали и сидели на них. Некоторые в больничных халатах ходили по комнатам. Первое лицо, встретившееся Ростову в офицерских палатах, был маленький, худой человечек без руки, в колпаке и больничном халате с закушенной трубочкой, ходивший в первой комнате. Ростов, вглядываясь в него, старался вспомнить, где он его видел.
– Вот где Бог привел свидеться, – сказал маленький человек. – Тушин, Тушин, помните довез вас под Шенграбеном? А мне кусочек отрезали, вот… – сказал он, улыбаясь, показывая на пустой рукав халата. – Василья Дмитриевича Денисова ищете? – сожитель! – сказал он, узнав, кого нужно было Ростову. – Здесь, здесь и Тушин повел его в другую комнату, из которой слышался хохот нескольких голосов.
«И как они могут не только хохотать, но жить тут»? думал Ростов, всё слыша еще этот запах мертвого тела, которого он набрался еще в солдатском госпитале, и всё еще видя вокруг себя эти завистливые взгляды, провожавшие его с обеих сторон, и лицо этого молодого солдата с закаченными глазами.
Денисов, закрывшись с головой одеялом, спал не постели, несмотря на то, что был 12 й час дня.
– А, Г'остов? 3до'ово, здо'ово, – закричал он всё тем же голосом, как бывало и в полку; но Ростов с грустью заметил, как за этой привычной развязностью и оживленностью какое то новое дурное, затаенное чувство проглядывало в выражении лица, в интонациях и словах Денисова.
Рана его, несмотря на свою ничтожность, все еще не заживала, хотя уже прошло шесть недель, как он был ранен. В лице его была та же бледная опухлость, которая была на всех гошпитальных лицах. Но не это поразило Ростова; его поразило то, что Денисов как будто не рад был ему и неестественно ему улыбался. Денисов не расспрашивал ни про полк, ни про общий ход дела. Когда Ростов говорил про это, Денисов не слушал.
Ростов заметил даже, что Денисову неприятно было, когда ему напоминали о полке и вообще о той, другой, вольной жизни, которая шла вне госпиталя. Он, казалось, старался забыть ту прежнюю жизнь и интересовался только своим делом с провиантскими чиновниками. На вопрос Ростова, в каком положении было дело, он тотчас достал из под подушки бумагу, полученную из комиссии, и свой черновой ответ на нее. Он оживился, начав читать свою бумагу и особенно давал заметить Ростову колкости, которые он в этой бумаге говорил своим врагам. Госпитальные товарищи Денисова, окружившие было Ростова – вновь прибывшее из вольного света лицо, – стали понемногу расходиться, как только Денисов стал читать свою бумагу. По их лицам Ростов понял, что все эти господа уже не раз слышали всю эту успевшую им надоесть историю. Только сосед на кровати, толстый улан, сидел на своей койке, мрачно нахмурившись и куря трубку, и маленький Тушин без руки продолжал слушать, неодобрительно покачивая головой. В середине чтения улан перебил Денисова.
– А по мне, – сказал он, обращаясь к Ростову, – надо просто просить государя о помиловании. Теперь, говорят, награды будут большие, и верно простят…
– Мне просить государя! – сказал Денисов голосом, которому он хотел придать прежнюю энергию и горячность, но который звучал бесполезной раздражительностью. – О чем? Ежели бы я был разбойник, я бы просил милости, а то я сужусь за то, что вывожу на чистую воду разбойников. Пускай судят, я никого не боюсь: я честно служил царю, отечеству и не крал! И меня разжаловать, и… Слушай, я так прямо и пишу им, вот я пишу: «ежели бы я был казнокрад…
– Ловко написано, что и говорить, – сказал Тушин. Да не в том дело, Василий Дмитрич, – он тоже обратился к Ростову, – покориться надо, а вот Василий Дмитрич не хочет. Ведь аудитор говорил вам, что дело ваше плохо.
– Ну пускай будет плохо, – сказал Денисов. – Вам написал аудитор просьбу, – продолжал Тушин, – и надо подписать, да вот с ними и отправить. У них верно (он указал на Ростова) и рука в штабе есть. Уже лучше случая не найдете.
– Да ведь я сказал, что подличать не стану, – перебил Денисов и опять продолжал чтение своей бумаги.
Ростов не смел уговаривать Денисова, хотя он инстинктом чувствовал, что путь, предлагаемый Тушиным и другими офицерами, был самый верный, и хотя он считал бы себя счастливым, ежели бы мог оказать помощь Денисову: он знал непреклонность воли Денисова и его правдивую горячность.
Когда кончилось чтение ядовитых бумаг Денисова, продолжавшееся более часа, Ростов ничего не сказал, и в самом грустном расположении духа, в обществе опять собравшихся около него госпитальных товарищей Денисова, провел остальную часть дня, рассказывая про то, что он знал, и слушая рассказы других. Денисов мрачно молчал в продолжение всего вечера.
Поздно вечером Ростов собрался уезжать и спросил Денисова, не будет ли каких поручений?
– Да, постой, – сказал Денисов, оглянулся на офицеров и, достав из под подушки свои бумаги, пошел к окну, на котором у него стояла чернильница, и сел писать.
– Видно плетью обуха не пег'ешибешь, – сказал он, отходя от окна и подавая Ростову большой конверт. – Это была просьба на имя государя, составленная аудитором, в которой Денисов, ничего не упоминая о винах провиантского ведомства, просил только о помиловании.
– Передай, видно… – Он не договорил и улыбнулся болезненно фальшивой улыбкой.


Вернувшись в полк и передав командиру, в каком положении находилось дело Денисова, Ростов с письмом к государю поехал в Тильзит.
13 го июня, французский и русский императоры съехались в Тильзите. Борис Друбецкой просил важное лицо, при котором он состоял, о том, чтобы быть причислену к свите, назначенной состоять в Тильзите.
– Je voudrais voir le grand homme, [Я желал бы видеть великого человека,] – сказал он, говоря про Наполеона, которого он до сих пор всегда, как и все, называл Буонапарте.
– Vous parlez de Buonaparte? [Вы говорите про Буонапарта?] – сказал ему улыбаясь генерал.
Борис вопросительно посмотрел на своего генерала и тотчас же понял, что это было шуточное испытание.
– Mon prince, je parle de l'empereur Napoleon, [Князь, я говорю об императоре Наполеоне,] – отвечал он. Генерал с улыбкой потрепал его по плечу.
– Ты далеко пойдешь, – сказал он ему и взял с собою.
Борис в числе немногих был на Немане в день свидания императоров; он видел плоты с вензелями, проезд Наполеона по тому берегу мимо французской гвардии, видел задумчивое лицо императора Александра, в то время как он молча сидел в корчме на берегу Немана, ожидая прибытия Наполеона; видел, как оба императора сели в лодки и как Наполеон, приставши прежде к плоту, быстрыми шагами пошел вперед и, встречая Александра, подал ему руку, и как оба скрылись в павильоне. Со времени своего вступления в высшие миры, Борис сделал себе привычку внимательно наблюдать то, что происходило вокруг него и записывать. Во время свидания в Тильзите он расспрашивал об именах тех лиц, которые приехали с Наполеоном, о мундирах, которые были на них надеты, и внимательно прислушивался к словам, которые были сказаны важными лицами. В то самое время, как императоры вошли в павильон, он посмотрел на часы и не забыл посмотреть опять в то время, когда Александр вышел из павильона. Свидание продолжалось час и пятьдесят три минуты: он так и записал это в тот вечер в числе других фактов, которые, он полагал, имели историческое значение. Так как свита императора была очень небольшая, то для человека, дорожащего успехом по службе, находиться в Тильзите во время свидания императоров было делом очень важным, и Борис, попав в Тильзит, чувствовал, что с этого времени положение его совершенно утвердилось. Его не только знали, но к нему пригляделись и привыкли. Два раза он исполнял поручения к самому государю, так что государь знал его в лицо, и все приближенные не только не дичились его, как прежде, считая за новое лицо, но удивились бы, ежели бы его не было.
Борис жил с другим адъютантом, польским графом Жилинским. Жилинский, воспитанный в Париже поляк, был богат, страстно любил французов, и почти каждый день во время пребывания в Тильзите, к Жилинскому и Борису собирались на обеды и завтраки французские офицеры из гвардии и главного французского штаба.
24 го июня вечером, граф Жилинский, сожитель Бориса, устроил для своих знакомых французов ужин. На ужине этом был почетный гость, один адъютант Наполеона, несколько офицеров французской гвардии и молодой мальчик старой аристократической французской фамилии, паж Наполеона. В этот самый день Ростов, пользуясь темнотой, чтобы не быть узнанным, в статском платье, приехал в Тильзит и вошел в квартиру Жилинского и Бориса.