Введение в AJAX и XHR — Сетевые запросы в JavaScript | Томаш Хмельницкий | Стартап

Томаш Хмельницкий

·

Читать

Опубликовано в

·

5 мин чтения

·

Окт 2 6, 2020

Photo by NASA on Unsplash

Что такое сетевой запрос

Всякий раз, когда вы отправляете URL-адрес из адресной строки вашего веб-браузера, вы делаете HTTP-запрос на сервер. То, что вы получаете от этого запроса, представляет собой HTML-документ, веб-сайт, который вы запрашивали. HTTP — это протокол, который позволяет нам это делать.

Чем полезен AJAX

В HTML мы можем ссылаться на другие документы, используя элемент a . После перехода по такой ссылке мы попадаем на другую страницу, указанную в атрибуте href . Проблема в том, что всю страницу нужно перезагрузить. Что, если мы не хотим, чтобы наши пользователи смотрели на белый экран? Может быть, нам нужно получить некоторые данные с сервера, но мы хотим заменить только часть нашей страницы? Вот где на помощь приходит AJAX.

Что такое AJAX

AJAX (асинхронный JavaScript и XML) — это просто способ использования JavaScript для получения данных с сервера без перезагрузки веб-сайта. XML — это формат данных, похожий на html, но в настоящее время JSON более распространен. JSON (нотация объектов JavaScript) — это данные в виде объектов JavaScript. Это формат, в котором мы хотим получать данные с сервера. Используя AJAX, мы можем асинхронно запрашивать некоторые данные в фоновом режиме с помощью JavaScript и отображать их пользователю после их получения. Нам больше не нужно перезагружать всю страницу.

Использование API

Чтобы получить эти данные, мы будем использовать то, что называется интерфейсом прикладного программирования. Это способ связи между программами. Это предоставит нашему коду JavaScript возможность делать запросы к серверу. Все, что нам нужно сделать в нашем случае, это использовать определенный URL-адрес, и сервер вернет нам данные на основе этого URL-адреса. Вот как мы можем сделать вызов API. В этом примере мы будем использовать общедоступный API для получения случайных изображений собак. Довольно круто, правда?

Выполнение запросов с помощью объекта XHR.

Чтобы сделать запрос ajax, мы будем использовать объект XMLHttpRequest . Давайте настроим шаблонный код. Во-первых, мы хотим создать объект с помощью конструктора:

 const xhr = new XMLHttpRequest() 

Теперь нам нужно указать метод HTTP, который мы собираемся использовать. Мы собираемся использовать метод GET. По сути, это означает, что если бы мы передавали какие-либо параметры в API, мы бы помещали их прямо в URL-адрес. Нам также необходимо указать URL-адрес, с которого мы хотим получить данные. Это API.

 const url = 'https://random.dog/woof.json' 
const xhr = new XMLHttpRequest()
xhr.open('GET', url)

Вы можете вставить URL-адрес в свой браузер и посмотреть, что подходит. Данные, возвращаемые нашему объекту xhr, по умолчанию имеют форму строки, но мы можем запросить объект. Давайте сделаем это.

 const url = 'https://random.dog/woof.json' 
const xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = 'json'

А вот и важная часть. Мы хотим передать функцию обратного вызова нашему xhr объект, который будет запущен, когда данные вернутся.

 const url = 'https://random.dog/woof.json'const xhr = new XMLHttpRequest() 
xhr.open('GET', url)
xhr.responseType = 'json'xhr.onload = () => console.log(xhr.response)

Это то же самое, что указать обработчик onclick . Предоставленная функция будет запущена после завершения запроса. Давайте запротоколируем данные, которые мы получаем с сервера. Он находится в свойстве response нашего xhr 9.0026 объект.

Теперь, чтобы отправить запрос, мы должны вызвать метод send :

 const url = 'https://random.dog/woof.json'const xhr = new XMLHttpRequest() 
xhr.open(' GET', url)
xhr. responseType = 'json'xhr.onload = () => console.log(xhr.response)
xhr.send()

Ура! Мы получаем объект с размером изображения и URL-адресом, который на него ссылается. Очевидно, что выводить его на консоль не так уж и интересно, но я оставляю это на ваше усмотрение, чтобы использовать то, что вы узнали. Подсказка: вы можете создать веб-сайт, на котором каждый раз, когда вы нажимаете кнопку, появляется случайная фотография собаки.

XHR является асинхронным

Поскольку для выполнения сетевого запроса требуется время, xhr по умолчанию является асинхронным. Это означает, что если мы попытаемся получить доступ к результату нашего запроса до его завершения, мы получим null .

 const url = 'https://random.dog/woof.json'const xhr = new XMLHttpRequest() 
xhr.open('GET', url)
xhr.responseType = 'json'xhr.onload = () => console.log(xhr.response)
//Функция обратного вызова регистрирует ответ после завершения запроса
xhr. send()console.log(xhr.response)
//Synchronous console.log запускается до завершения асинхронного сетевого запроса, печатает null

Обработка ошибок с помощью XHR

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

Когда запрос вообще не может быть отправлен, запускается событие error . Мы можем указать, что делать, когда это произойдет, передав другой обратный вызов:

 xhr.onerror = () => console.log('Произошла ошибка сети. Проверьте подключение к Интернету и повторите попытку.') 

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

Событие загрузки будет выполнено, даже если состояние ответа, например, 404 . Вот почему нам нужно проверить статус внутри обратного вызова onload :

 xhr. onload = () => { 
if (xhr.status !== 200) {
console.log(`Ошибка ${xhr.status}: ${xhr.statusText}`)
} else {
console.log(xhr.response)
}
}

Если все сделано правильно, статус будет 200. Мы можем получить код состояния из xhr.status и соответствующее сообщение из xhr.statusText . Если бы произошла ошибка, результатом нашего console.log было бы что-то вроде «Ошибка 404: Не найдено».

Это окончательный код с реализованной обработкой ошибок:

 const url = 'https://random.dog/woof.json'const xhr = new XMLHttpRequest() 
xhr.open('GET', url)
xhr.responseType = 'json'xhr.onload = () => {
if (xhr.status !== 200) {
console.log(`Ошибка ${xhr.status}: ${xhr.statusText}`)
} else {
console.log(xhr.response)
}
}xhr.onerror = () => console.log('Произошла ошибка сети. Проверьте подключение к Интернету и повторите попытку.')xhr.send()

Замените URL-адрес на что-то вроде «https:/ /random. dog/woof.json/aaa», чтобы проверить, правильно ли обрабатывается ошибка 404. Вы также можете заменить URL-адрес недействительным, например «https://aaa», чтобы увидеть onerror обработчик событий в действии.

Заключение

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

Сетевые запросы в современном JavaScript

Для XHR требуется довольно много шаблонного кода. Нам нужно сконструировать объект, каждый раз задавать метод HTTP и явно отправить запрос. Он также полагается на функции обратного вызова, которые могут запутаться в сложных сценариях, если не будут обработаны должным образом. В современном JavaScript мы используем функцию fetch для сетевых запросов. Он использует обещания ES6 и является более гибким и мощным. Прочтите мою статью о fetch и Promises, чтобы узнать, как упростить сетевые запросы!

Настроить Real User Monitoring для захвата действий XHR

Современные веб-приложения не полагаются на загрузку страниц для изменения пользовательского интерфейса после ввода данных пользователем. Вместо этого каждое взаимодействие с пользователем инициирует один или несколько запросов XHR для получения необходимых данных, тем самым изменяя только части пользовательского интерфейса. Когда вы активируете поддержку XHR-действий, вы добавляете видимость каждому типу взаимодействия с пользователем, а не только обычным загрузкам страниц, которые фиксируются по умолчанию. Эта опция значительно расширяет видимость в средах одностраничных приложений (SPA), созданных поверх AngularJS, React или других фреймворков JavaScript.

Поддерживаемые фреймворки JavaScript

Поскольку существует очень много разных фреймворков JavaScript, мы фокусируем нашу поддержку на самых популярных из них, но это не означает, что вы не получаете действия XHR для фреймворков, которых нет в списке на страницах конфигурации. Для перечисленных Dynatrace предлагает специальную поддержку, в то время как общие настройки охватывают все другие популярные фреймворки, такие как React, Ember.js, Google Web Toolkit и реализации Vanilla JavaScript.

Причина, по которой Dynatrace перечисляет некоторые фреймворки, конкретно связана с захватом ввода имен действий пользователя, таких как Нажмите «Поиск» . Чтобы определить заголовок «Поиск» из примера и соответствующий XHR-запрос, Dynatrace требуется специальная поддержка таких фреймворков, как AngularJS, jQuery, Dojo, Ext JS, Sencha Touch, Backbone.js, MooTools и Prototype.

Включение поддержки определенных фреймворков JavaScript

Включение поддержки определенных фреймворков JavaScript

  1. В меню Dynatrace перейдите к Web .
  2. Выберите приложение, которое вы хотите настроить.
  3. В правом верхнем углу страницы обзора приложения выберите Дополнительно ( ) > Редактировать .
  1. В настройках приложения перейдите к Захват > Асинхронные веб-запросы и SPA .

  2. В разделе Поддержка платформы JavaScript выберите одну из платформ JavaScript, подходящую для вашего веб-приложения. Для Angular вам может потребоваться ввести имя пакета.

    Что такое имя пакета Angular?

    Начиная с Angular версии 12, вы должны указать имя пакета Angular вашего приложения в настройках Dynatrace. В противном случае Real User Monitoring не будет работать.

    Для Angular 12 имя пакета зависит от имени проекта и больше не является статическим, а для Angular 11 и более ранних версий имя пакета всегда webpackjsonp .

    Чтобы найти имя пакета Angular для вашего приложения

    1. Откройте инструменты разработчика вашего браузера и перейдите к Консоль вкладка.

    2. Начните вводить webpackChunk . Браузер должен отобразить имя пакета для вашего приложения Angular. Скопируйте это имя.

      Например, имя пакета на снимке экрана ниже — webpackChunklite .

      Если вы видите в консоли несколько записей webpackChunk , выберите ту, которая соответствует имени вашего приложения. Кроме того, попробуйте отключить расширения браузера, чтобы получить более чистый список. Если нет webpackChunk записей в консоли, возможно, вы используете Angular версии 11 или более ранней. В этом случае вам не нужно указывать имя пакета Angular.

    3. Вставьте имя, скопированное на шаге 2, в поле Имя пакета Angular в настройках вашего приложения.

Активировать общую поддержку фреймворков JavaScript

Если ваше приложение использует фреймворк JavaScript, который Dynatrace явно не поддерживает, вы можете включить общую поддержку веб-запросов XHR и fetch().

  1. В меню Dynatrace перейдите к Web .
  2. Выберите приложение, которое вы хотите настроить.
  3. В правом верхнем углу страницы обзора приложения выберите Дополнительно ( ) > Редактировать .
  1. В настройках приложения перейдите к Захват >
    Асинхронные веб-запросы и SPA
    .
  2. В разделе Общая поддержка включите необходимые параметры:
    • Включить Захват запросов fetch() для сбора данных о действиях пользователя для запросов на основе Fetch API.
    • Включите Capture XmlHttpRequest (XHR) для захвата любого взаимодействия, которое приводит к вызову XmlHttpRequest в качестве действия XHR.

Включить поддержку действий по времени

В зависимости от платформы XHR (AJAX) или архитектуры приложения может дополнительно потребоваться включить параметр поддержки действий по времени.

Этот параметр необходим, когда приложение не инициирует вызовы XHR (AJAX) непосредственно в обработчиках событий HTML-элементов, а вместо этого откладывает их через SetTimeout вызовов.

  1. В меню Dynatrace перейдите к Web .
  2. Выберите приложение, которое вы хотите настроить.
  3. В правом верхнем углу страницы обзора приложения выберите Дополнительно ( ) > Редактировать .
  1. В настройках приложения выберите Захват > Захват содержимого .
  1. Включить
    Поддержка действий по времени
    .

Исключить определенные вызовы XHR из мониторинга

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

Чтобы исключить вызовы XHR из мониторинга

  1. В меню Dynatrace перейдите к Web .
  2. Выберите приложение, которое вы хотите настроить.
  3. В правом верхнем углу страницы обзора приложений выберите Дополнительно ( ) > Редактировать .
  1. В настройках приложения перейдите к Захват > Исключения XHR .
  2. Выберите Добавьте правило исключения XHR и укажите регулярное выражение, соответствующее URL-адресам, которые не должны становиться действиями XHR.

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

Вы также можете настроить Real User Monitoring с помощью RUM JavaScript API.

Отсутствуют действия XHR при использовании обещаний

Когда используются обещания, Dynatrace не всегда создает действия пользователя, поэтому вы можете заметить, что некоторые действия XHR отсутствуют.

Как Dynatrace обычно создает действия пользователя:

  1. Регистрируется взаимодействие пользователя со страницей, например щелчок, нажатие клавиши или событие прокрутки.
  2. Если запрос XHR или выборка запускается в течение следующих 30 миллисекунд, создается действие пользователя. Если запрос начинается позже, действие пользователя не создается.

Таймфрейм в 30 мс продлевается на неопределенный срок для текущего синхронного выполнения, например, когда долгий расчет в коде приложения занимает более 30 мс и запрос XHR начинается только после завершения расчета. Однако это применимо только тогда, когда выполнение выполняется непосредственно в обработчике событий и

setTimeout , setInterval или промисы не используются.