Запрос XMLHttpRequest()

XMLHttpRequest – это API, который предоставляет клиенту функциональность для обмена данными между клиентом и сервером (предоставляет простой способ получения данных по ссылке без перезагрузки страницы). Это позволяет обновлять только часть веб-страницы, не прерывая действий пользователя. Метод XMLHttpRequest() используется в AJAX запросах и, особенно, в single-page приложениях.

Замечания:

  1. XMLHttpRequest может работать с любыми данными, а не только с XML.
  2. На сегодняшний день не обязательно использовать XMLHttpRequest(), так как существует более современный метод fetch().

Режимы работы XMLHttpRequest:

  1. синхронный;
  2. асинхронный.

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

Асинхронный режим работы XMLHttpRequest

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

  1. Создать объект XMLHttpRequest.
  2. Инициализировать запрос, используя метод open().
  3. Послать запрос, используя метод send().
  4. Слушать следующие события на XMLHttpRequest, чтобы получить ответ:
    • load – происходит, когда получен какой-либо ответ (включая ответы с HTTP-ошибкой, например, 404);
    • error – когда запрос не может быть выполнен (например, нет соединения или невалидный URL);
    • progress – происходит периодически во время загрузки ответа, сообщает о прогрессе.
Пример

[свернуть]

Объект XMLHttpRequest

Объект XMLHttpRequest создается с помощью конструкции new:

Новый объект XMLHttpRequest должен быть подготовлен вызовом функции open() перед вызовом send() для отправки запроса на сервер.

Метод XMLHttpRequest.open()

Метод XMLHttpRequest.open() (https://developer.mozilla.org) инициализирует новый запрос или повторно инициализирует уже созданный запрос:

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

  • method - для HTTP-запроса используются такие методы как "GET", "POST", "PUT", "DELETE", и т. д. (игнорируется для URL, отличных от HTTP(S)-запросов);
  • url - DOMString, представляет URL для отправки запроса;
  • async (необязательный, по умолчанию true) - логический параметр, указывает выполнять операцию асинхронно или нет:
    1. если false, метод send() не возвращается, пока не будет получен ответ;
    2. если true, уведомление о получении ответа осуществляется с помощью обработчика события (должен быть true, если атрибут multipart равен true, иначе будет выброшено исключение).
  • user (необязательный, по умолчанию null) - имя пользователя, использующееся для аутентификации;
  • password (необязательный, по умолчанию null) - пароль, использующийся для аутентификации.

Особенности метода XMLHttpRequest.open():

  1. Вызов open() не открывает соединение (он лишь конфигурирует запрос), отсылка на сервер - после вызова send().
  2. Вызов метода XMLHttpRequest.open() для уже активного запроса (для которого уже был вызван open()) эквивалентно вызову abort().
Методы HTTP-запроса (GET, POST, и т.д.

https://developer.mozilla.org/ru/docs/Web/HTTP/Methods

  • GET – получить определённый ресурс (например, HTML-файл, содержащий информацию о товаре или список товаров);
  • HEAD – получить метаданные об определённом ресурсе без получения содержания (например, вы можете использовать запрос HEAD, чтобы узнать, когда ресурс в последний раз обновлялся, и только потом использовать (более «затратный») запрос GET, чтобы загрузить сам ресурс, если он был изменён);
  • POST – создать новый ресурс (например, добавить новую статью или новый контакт в базу данных);
  • PUT – обновить существующий ресурс (или создать новый, если таковой не существует). Всегда идемпотентен. Операция считается идемпотентной, если её многократное выполнение приводит к тому же результату, что и однократное выполнение (например, если автоинкрементное поле является важной частью ресурса, то PUT перезапишет его (т.к. он перезаписывает всё), а вот PATCH (см. ниже) может и не перезаписать;
  • DELETE – удалить определённый ресурс;
  • TRACE - выполняет проверку обратной связи по пути к целевому ресурсу, предоставляя полезный механизм отладки;
  • OPTIONS - используется для описания параметров соединения с целевым ресурсом;
  • CONNECT - запускает двустороннюю связь с запрошенным ресурсом (метод можно использовать для открытия туннеля);
  • PATCH – частично изменяет ресурс (при этом, в отличие от PUT может как быть идемпотентным, так и не быть, который всегда идемпотентен.
  • Операция считается идемпотентной, если её многократное выполнение приводит к тому же результату, что и однократное выполнение (например, если автоинкрементное поле является важной частью ресурса, то PUT перезапишет его (т.к. он перезаписывает всё), а вот PATCH (см. ниже) может и не перезаписать.

[свернуть]

Передача URL с параметрами

Отсюда https://learn.javascript.ru/xmlhttprequest

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

Метод XMLHttpRequest.send()

Метод XMLHttpRequest.send()  (https://developer.mozilla.org/) устанавливает соединение и отсылает запрос к серверу:

  • eсли запрос асинхронный (каким он является по умолчанию), то возврат из данного метода происходит сразу после отправления запроса;
  • если запрос синхронный, то метод возвращает управление только после получения ответа.

где body (необязательный, по умолчанию null) - данные, отправляемые в запросе, например:

  • Document, в этом случае данные будут сериализованы перед отправкой;
  • BodyInit, которые, согласно спецификации Fetch, могут быть Blob, BufferSource (en-US), FormData, URLSearchParams, ReadableStream (en-US), или объектом USVString.

Лучший способ передать двоичные данные (например при загрузке файлов) - это использование ArrayBufferView или Blobs в сочетании с методом send().

Особенности метода XMLHttpRequest.send():

  1. Если метод запроса GET или HEAD, то аргументы игнорируются и тело запроса устанавливается в null.
  2. Если заголовок Accept не был задан с помощью setRequestHeader(), будет отправлено значение Accept по умолчанию */*.

Прослушивание событий XMLHttpRequest

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

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

[свернуть]

Для событий доступны следующие свойства (только для чтения):

    1. lengthComputable - логический флаг, указывающий поддается ли расчету общая работа, которую необходимо выполнить базовым процессом, и объем уже выполненной работы (другими словами, измеряем ли прогресс процесса или нет; true, если сервер присылает заголовок Content-Length);
    2. loaded - 64-битное целое число без знака, указывающее объем работы, уже выполненной базовым процессом (при загрузке ресурса с использованием HTTP учитывается только тело HTTP-сообщения и не включаются заголовки и другие служебные данные);
    3. total - 64-битное целое число без знака, представляющее общий объем работы, которую выполняет базовый процесс (при загрузке ресурса с использованием HTTP, это - Content-Length (размер тела сообщения), не включает заголовки и другие служебные данные; только если lengthComputable равно true).

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

  • status - rод состояния HTTP (число: 200, 404, 403 и так далее, может быть 0 в случае, если ошибка не связана с HTTP);
  • statusText - сообщение о состоянии ответа HTTP (строка: обычно OK для 200, Not Found для 404, Forbidden для 403, и так далее);
  • response (в старом коде - responseText) - тело ответа сервера;
  • responseType - ожидаемый тип ответа сервера (позволяет автору изменить тип ответа):
    1. "" (по умолчанию) – строка;
    2. "text" – строка;
    3. "arraybuffer" – ArrayBuffer (для бинарных данных);
    4. "blob" – Blob (для бинарных данных);
    5. "document" – XML-документ (может использовать XPath и другие XML-методы);
    6. "json" – JSON (парсится автоматически, пример здесь).

Можно также указать таймаут (промежуток времени в миллисекундах), в течение которого мы готовы ждать ответ:

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

Возвращение результатов функции, выполняемой при наступлении события

[свернуть]

Состояния асинхронного запроса XMLHttpRequest 

У XMLHttpRequest есть состояния, которые меняются по мере его выполнения.

Текущее состояние запроса можно посмотреть в свойстве xhr.readyState.

Список всех состояний, указанных в спецификации:

  • UNSENT = 0;  (исходное состояние);
  • OPENED = 1; (вызван метод open);
  • HEADERS_RECEIVED = 2; (получены заголовки ответа);
  • LOADING = 3; (ответ в процессе передачи, данные частично получены);
  • DONE = 4; (запрос завершён).

Состояния объекта XMLHttpRequest меняются в таком порядке: 0 → 1 → 2 → 3 → … → 3 → 4 (состояние 3 повторяется каждый раз, когда получена часть данных).

Изменения в состоянии объекта запроса генерируют событие readystatechange (устар.):

Из-за появления событий load, error, progress можно считать, что событие readystatechange устарело.

Отмена асинхронного запроса XMLHttpRequest 

Если мы передумали делать запрос, можно отменить его вызовом метода abort():

При этом генерируется событие abort, а xhr.status устанавливается в 0.

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

Если в методе open() третий параметр async установлен на false, запрос выполняется синхронно: выполнение JavaScript останавливается на send() и возобновляется после получения ответа (пример здесь).

Синхронные запросы используются редко, так как они блокируют выполнение JavaScript до тех пор, пока загрузка не завершена.

Работа XMLHttpRequest с HTTP-заголовками

Подробнее о HTTP-заголовках

на https://developer.mozilla.org/ru/docs/Web/HTTP/Headers

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

В HTTP-заголовке содержится не чувствительное к регистру название, а затем после (:) непосредственно значение. Пробелы перед значением игнорируются.

Заголовки и их статусы перечислены в реестре IANA, который постоянно обновляется.

Заголовки могут быть сгруппированы по следующим контекстам:

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

[свернуть]

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

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

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

  1. setRequestHeader(name, value) - устанавливает заголовок запроса с именем name и значением value.
  2. getResponseHeader(name) - возвращает значение заголовка ответа name (кроме Set-Cookie и Set-Cookie2).
Метод setRequesrHeader()

Метод setRequestHeader(name, value) устанавливает заголовок запроса с именем name и значением value, например:

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

Например:

[свернуть]
Метод getResponseHeader()

Метод getResponseHeader(name) - возвращает значение заголовка ответа name (кроме Set-Cookie и Set-Cookie2), например:

[свернуть]
Метод getAllResponseHeaders()

Метод getAllResponseHeaders() - возвращает все заголовки ответа (кроме Set-Cookie и Set-Cookie2) в виде единой строки, например:

Значение заголовка всегда отделено двоеточием с пробелом ":" (этот формат задан стандартом).

Между заголовками всегда стоит перевод строки в два символа "\r\n" (независимо от ОС), так что мы можем легко разделить их на отдельные заголовки, например так (если два заголовка имеют одинаковое имя, то последний перезаписывает предыдущий):

[свернуть]

Запрос POST (объект FormData)

Подробнее о POST

подробнее https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

HTTP-метод POST предназначен для отправки данных на сервер. Тип тела запроса указывается в заголовке Content-Type.

Отличие PUT от POST:

  • PUT является идемпотентным: повторное его применение даёт тот же результат, что и при первом применении (то есть у метода нет побочных эффектов), тогда как повторный вызов одного и того же метода POST может иметь такие эффекты, как например, оформление одного и того же заказа несколько раз.

Запрос POST обычно отправляется через форму HTML и приводит к изменению на сервере. В этом случае тип содержимого выбирается путём размещения соответствующей строки в атрибуте enctype элемента <form> или formenctype атрибута элементов <input> или <button>:

  • application/x-www-form-urlencoded: значения кодируются в парах с ключом, разделённых символом '&', с '=' между ключом и значением; не буквенно-цифровые символы - это причина, по которой данный тип не подходит для использования с двоичными данными (вместо этого используйте multipart/form-data);
  • multipart/form-data: каждое значение посылается как блок данных ("body part"), с заданными пользовательским клиентом разделителем ("boundary"), разделяющим каждую часть (ключи задаются в заголовке Content-Disposition каждой части);
  • text/plain - когда запрос POST отправляется с помощью метода, отличного от HTML-формы (например, через XMLHttpRequest, тело может принимать любой тип).

[свернуть]
Пример POST через XMLHttpRequest

[свернуть]

Чтобы сделать POST-запрос, мы можем использовать встроенный объект FormData.

Синтаксис:

Примеры

Обычно форма отсылается в кодировке multipart/form-data.

Если нам больше нравится формат JSON, то используем JSON.stringify и отправляем данные как строку.

Подробнее

Важно не забыть поставить соответствующий заголовок Content-Type: application/json, многие серверные фреймворки автоматически декодируют JSON при его наличии:

Метод send(body) может отправить практически что угодно в body, включая объекты типа Blob и BufferSource.

[свернуть]

Прогресс отправки (XMLHttpRequest.upload)

Событие progress срабатывает только на стадии загрузки ответа с сервера, но не показывает прогресс отправки данных на сервер.

Свойство XMLHttpRequest.upload возвращает объект XMLHttpRequestUpload, представляющий процесс загрузки, и к которому можно добавить следующие обработчики событий:

  • onloadstart - начало загрузки;
  • onprogress - передача данных;
  • onabort - отмена загрузки;
  • onerror - ошибка при загрузки;
  • onload - загрузка завершилась;
  • ontimeout - загрузка не завершилась ко времени, указанному автором;
  • onloadend - загрузка завершилась (успешно или с ошибкой).
Примеры обработчиков

[свернуть]

Запросы с XMLHttpRequest на другой источник

XMLHttpRequest может осуществлять запросы на другие сайты, используя ту же политику CORS, что и fetch.

Подробнее о CORS

Cross-Origin Resource Sharing (CORS) — механизм, использующий дополнительные HTTP-заголовки, чтобы дать возможность агенту пользователя получать разрешения на доступ к выбранным ресурсам с сервера на источнике (домене), отличном от того, что сайт использует в данный момент.

Агент пользователя делает запрос с другого источника (cross-origin HTTP request), если источник текущего документа отличается от запрашиваемого ресурса доменом, протоколом или портом.

[свернуть]

Как и при работе с fetch, по умолчанию на другой источник не отсылаются куки и заголовки HTTP-авторизации. Чтобы это изменить, необходимо установить свойство xhr.withCredentials в true:

 

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

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.