XMLHttpRequest

Объект XMLHttpRequest - это API, который дает возможность из JavaScript делать HTTP-запросы к серверу без перезагрузки страницы и извлекать данные из ответа сервера. Название XMLHttpRequest является историческим и не имеет никакого отношения к его функциональности.

Пример запроса

Для начала рассмотрим пример получения данных при обращении на внешний сервер swapi.co.

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
    </head>
    <body>
      <button id="btn" type="submit">GET</button>
      <script src="js/script.js"></script>
    </body>
    </html>
  2. Следующий шаг - создание объекта XMLHttpRequest в файле script.js. Данный объект предоставляет функционал для обмена данными между клиентом (браузер) и сервером. Также нам нужно будет получить доступ к идентификатору кнопки.

    const btn = document.getElementById('btn')
    const request = new XMLHttpRequest()

    Примечание

    Данные с сервера мы будем получать в формате JSON, поскольку это один из наиболее удобных форматов данных при взаимодействии с JavaScript.

  3. К примеру, мы хотим получить данные про героя серии фильмов "Звездные войны" - Люка Скайвокера. Для этого нам необходимо произвести инициализацию соединения.

    request.open('GET', 'https://swapi.co/api/people/1')

    Метод open принимает 5 аргументов:

    • method - GET, POST, PUT, DELETE.

    • url - адрес сервера, куда необходимо отправить запрос (также это может быть адрес нужного нам файла)

    • async - асинхронность запроса (по умолчанию true).

    • login - учетные данные для авторизации.

    • pass - учетные данные для авторизации.

  4. Поскольку запрос асинхронный, установим специальный обработчик изменения свойства readyState для получения данных от сервера.

    XMLHttpRequest имеет следующие свойства:

    • status - статус обработки данных (например 200, 304, 404)

    • statusText - статус обработки данных строкой(например OK, Not found и т.д.)

    • responseText or response (данные с сервера)

    • readyState (этапы отправки и получения данных):

      • 0 - UNSENT - Объект был создан. Метод open() еще не вызывался.

      • 1 - OPENED - Метод open() был вызван.

      • 2 - HEADERS_RECEIVED - Метод send() был вызван, доступны заголовки (headers) и статус.

      • 3 - LOADING - Загрузка; responseText содержит частичные данные.

      • 4 - DONE - Операция полностью завершена.

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

    • readyState должен быть равен 4 (то есть операция была полностью завершена)

    • status должен быть равен 200 (успешное получение ответа).

    request.onreadystatechange = function() {
      if (request.readyState === 4 && request.status === 200) {
        const res = JSON.parse(request.response)
        console.log(res)
      }
    }
  5. Теперь, когда сам запрос готов, необходимо отправить его на сервер. Для этого нам нужно вызывать специальный метод send().

    request.send()

    Важно!

    Файл ".html" необходимо запускать в режиме редактора "Live Preview". К примеру, в IntelliJ IDEA / Webstorm это:

    A в VS Code:

  6. В результате в консоли мы можем увидеть, что нам пришли данные от сервера в формате JSON, которые были преобразованы в обычный объект JavaScript.

    xhr

Также на ресурсе httpbin.org есть возможность потестировать запросы по остальным HTTP методам, например POST, но тогда в этом случае код нужно будет немного изменить соблюдая следующие правила:

  • Данные перед отправкой нужно привести в JSON формат.

  • Перед отправкой нужно указать заголовки запроса, используя метод setRequestHeader(). К примеру, в запросах клиента заголовок Content-Type сообщает серверу, в каком формате передаваются данные.

Данный пример показан с соблюдением пунктов, указанных выше:

const obj ={
  title: "Test title",
  body: "test text"
}

const request = new XMLHttpRequest()

request.open('POST', 'https://httpbin.org/post')
request.setRequestHeader('Content-type', 'application/json; charset=utf8') // Указываем серверу, что данные будут передавать в формате JSON и в кодировке UTF-8

request.onreadystatechange = function() {   
  if (request.readyState === 4 && request.status === 200) {
    let res = JSON.parse(request.response)
    console.log(res)
  }
}

request.send(JSON.stringify(obj)) // Отправляем объект "obj" на сервер, предварительно преобразовав его в формат JSON

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

xhr

Рассмотрим некоторые нюансы получения данных

Допустим, нам нужно получить с сервера картинку. Для этого можно использовать ресурс starwars-visualguide.com

Поскольку картинка приходит асинхронно в двоичном формате, необходимо вызвать метод URL.createObjectURL() у объекта window, который создает DOMString, содержащий URL с указанием на объект. Новый URL объект может представлять собой Blob объект, который в свою очередь представляет из себя объект наподобие файла с неизменяемыми, необработанными данными. Blob-ы представляют данные, которые могут быть не в родном формате JavaScript, что позволит сохранить картинку на странице.

const img = document.createElement('img')

const req = new XMLHttpRequest()

req.open('GET', `https://starwars-visualguide.com/assets/img/characters/1.jpg`)
req.responseType = 'blob'

req.addEventListener('readystatechange', function() {
  const binaryData = []

  if (this.readyState === 4 && this.status === 200) {
    binaryData.push(this.response)
    img.src = window.URL.createObjectURL(new Blob(binaryData, {type: "image/jpeg"}))
    console.log(img.src)
    document.body.appendChild(img)
    console.log(this.response)
  }
})

req.send()

Результат выполнения запроса будет следующим:

xhr

В консоль инспектора мы вывели ссылку на картинку и сам обьект Blob, внутри которого есть два аргумента: объем и формат картинки.

Полезные ссылки

1. Более детальное описание возможностей XMLHttpRequest 2. Основы работы XMLHttpRequest 3. Работа Blob обьектам

Last updated