Javascript свойство xmlhttprequest.status

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

<!DOCTYPE html>
<html>
	<head>
		<title>Использование JavaScript методов open() и send() объекта XMLHttpRequest</title>
	</head>
	<body>
		<button onclick = "getPhone()">Запросить телефон</button> <!-- добавляем атрибут событий onclick -->
		<div id = "demo"></div>
		<script>
	function getPhone() {
	  let xhr = new XMLHttpRequest(); // инициализируем переменную новым объектом XMLHttpRequest
	  xhr.open("GET", "user.json"); // определяем параметры для запроса 
	  xhr.send(); // отправляем запрос на сервер

	  xhr.onreadystatechange = function() {
	    // проверяем состояние запроса и числовой код состояния HTTP ответа
	    if (this.readyState == 4 && this.status == 200) {
	      const data = JSON.parse(this.responseText); // анализируем строку в формате JSON и инициализируем переменную значением, полученным в ходе анализа
	      document.getElementById("demo").innerHTML = "Телефон пользователя: " + data.phone; // находим элемент по id и изменяем его содержимое значением ключа объекта, содержащегося в переменной
	    }
	  }; 
	}
		</script>
	</body>
</html>

В этом примере с использованием атрибута событий onclick при нажатии на кнопку (HTML элемент <button>) вызываем функцию getPhone, которая:

Вызывает конструктор объекта XMLHttpRequest и инициализирует переменную новым объектом этого типа.
С помощью метода open() объекта XMLHttpRequest определяем параметры для запроса — указываем, что HTTP запрос будет осуществлен методом «GET», а в качестве URL адреса на который будет отправлен запрос мы задаем файл формата json

Обратите внимание, что файл размещен на том же сервере и в том же каталоге, что и документ с которого выполняется скрипт. Файл имеет следующий вид:

{
«firstName»: «Василий»,
«lastName»: «Джейсонов»,
«age»: 25,
«phone»: 88005553535
}

С помощью метода send() объекта XMLHttpRequest отправляем запрос на сервер.
С использованием обработчика событий onreadystatechange, вызываемого при запуске события readystatechange, то есть при каждом изменении свойства readyState объекта XMLHttpRequest мы вызываем функцию, которая проверяет состояние запроса, оно должно соответствовать значению 4 (операция полностью завершена) и числовой код состояния HTTP ответа (свойство status) должен соответствовать значению 200 (успешный запрос)

Если условия выполнены, то с использованием метода JSON.parse() анализируем строку в формате JSON и инициализируем переменную значением, полученным в ходе анализа. После этого с помощью метода getElementById() находим элемент с определенным глобальным атрибутом id и изменяем его содержимое значением ключа объекта, содержащегося в инициализированной ранее переменной.

Результат нашего примера:

Пример использования методов open() и send() объекта XMLHttpRequestJavaScript XMLHttpRequest

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

Различают два использования XmlHttpRequest. Первое — самое простое, синхронное.

Синхронный XMLHttpRequest

В этом примере через XMLHTTPRequest с сервера запрашивается страница http://example.org/, и текст ответа сервера показывается через alert().

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', false);
xmlhttp.send(null);
if(xmlhttp.status == 200) {
  alert(xmlhttp.responseText);
}

Здесь сначала создается запрос, задается открытие () синхронного соединение с адресом /xhr/test.html и запрос отсылается с null,
т.е без данных.

При синхронном запросе браузер «подвисает» и ждет на строчке 3, пока сервер не ответит на запрос. Когда ответ получен — выполняется строка 4, код ответа сравнивается с 200 (ОК), и при помощи alert
печатается текст ответа сервера. Все максимально просто.

Свойство responseText получит такой же текст страницы, как браузер, если бы Вы в перешли на /xhr/test.html. Для сервера
GET-запрос через XmlHttpRequest ничем не отличается от обычного перехода на страницу.

Асинхронный XMLHttpRequest

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

var xmlhttp = getXmlHttp()
xmlhttp.open('GET', '/xhr/test.html', true);
xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4) {
     if(xmlhttp.status == 200) {
       alert(xmlhttp.responseText);
         }
  }
};
xmlhttp.send(null);

Асинхронность включается третьим параметром функции open. В отличие от синхронного запроса, функция send() не останавливает
выполнение скрипта, а просто отправляет запрос.

Запрос xmlhttp регулярно отчитывается о своем состоянии через вызов функции xmlhttp.onreadystatechange. Состояние под номером 4 означает конец выполнения, поэтому функция-обработчик
при каждом вызове проверяет — не настало ли это состояние.

Вообще, список состояний readyState такой:

  • 0 — Unitialized
  • 1 —
  • 2 — Loaded
  • 3 — Interactive
  • 4 — Complete

Состояния 0-2 вообще не используются.

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

Firefox дает такой доступ, но для обработки запроса по частям состояние Interactive все равно неудобно из-за сложностей обнаружения ошибок соединения.
Поэтому Interactive тоже не используется.

На практике используется только последнее, Complete.

Если хотите углубиться в тонкости багов браузеров c readyState, отличными от 4, то многие из них рассмотрены в статье на.

Не используйте синхронные запросы

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

  1. Делаем асинхронный запрос
  2. Рисуем анимированную картинку или просто запись типа «Loading…»
  3. В onreadystatechange при достижении состояния 4 убираем Loading и, в зависимости от status вызываем обработку ответа или ошибки.

Кроме того, иногда полезно ставить ограничение на время запроса. Например, хочется генерировать ошибку, если запрос висит более 10 секунд.

Для этого сразу после send() через setTimeout ставится вызов обработчика ошибки, который очищается при получении ответа и обрывает запрос с генерацией ошибки,
если истекли 10 секунд.

Таймаут на синхронный запрос ставить нельзя, браузер может висеть долго-долго.. А вот на асинхронный — пожалуйста.

Этот пример демонстрирует такой таймаут.

var xmlhttp = getXmlHttp()
xmlhttp.open("POST", "/someurl", true);
xmlhttp.onreadystatechange=function(){
  if (xmlhttp.readyState != 4) return
  clearTimeout(timeout) // очистить таймаут при наступлении readyState 4
  if (xmlhttp.status == 200) {
      // Все ок
      ...
      alert(xmlhttp.responseText);
      ...
  } else {
      handleError(xmlhttp.statusText) // вызвать обработчик ошибки с текстом ответа
  }
}
xmlhttp.send("a=5&b=4");
// Таймаут 10 секунд
var timeout = setTimeout( function(){ xmlhttp.abort(); handleError("Time over") }, 10000);
function handleError(message) {
  // обработчик ошибки
  ...
  alert("Ошибка: "+message)
  ...
}

Как работает HTTP, и зачем нам это знать

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

Протокол HTTP очень прост и состоит, по сути, из двух частей:

  • Заголовков запроса/ответа;
  • Тела запроса/ответа.

Сначала идёт список заголовков, затем пустая строка, а затем (если есть) тело запроса/ответа.

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

1. Браузер пользователя устанавливает соединение с сервером vk.com и отправляет следующий запрос:

GET / HTTP/1.1
Host: vk.com

2. Сервер принимает запрос и отправляет ответ:

3. Браузер принимает ответ и показывает готовую страницу

Больше всего нам интересен самый первый шаг, где браузер инициирует запрос к серверу vk.com
Рассмотрим подробнее, что там происходит. Первая строка запроса определяет несколько важных параметров, а именно:

  • Метод, которым будет запрошен контент;
  • Адрес страницы;
  • Версию протокола.

— это метод (глагол), который мы применяем для доступа к указанной странице. является самым часто используемым методом, потому что он говорит серверу о том, что клиент всего лишь хочет прочитать указанный документ. Но помимо есть и другие методы, один из них мы рассмотрим уже в следующем разделе.

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

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

Сервер, получив запрос, ищет у себя сайт с доменом из заголовка , а также указанную страницу.
Если запрошенный сайт и страница найдены, клиенту отправляется ответ:
Такой ответ означает, что всё хорошо, документ найден и будет отправлен клиенту. Если говорить более обобщённо, стартовая строка ответа имеет следующую структуру:

Больше всего здесь интересен именно код состояния, он же код ответа сервера.
В этом примере код ответа — 200, что означает: сервер работает, документ найден и будет передан клиенту. Но не всегда всё идет гладко.
Например, запрошенный документ может отсутствовать или сервер будет перегружен, в таком случае клиент не получит контент, а код ответа будет отличным от 200.

  • 404 — если сервер доступен, но запрошённый документ не найден;
  • 503 — если сервер не может обрабатывать запросы по техническим причинам.

Спецификация HTTP 1.1 определяет 40 различных кодов HTTP.

После стартовой строки следуют заголовки, а затем тело ответа.

Объект XMLHttpRequest

Краеугольным камнем Ajax является объект XMLHttpRequest. Этот объект чрезвычайно полезен и обманчиво прост. По сути, он позволяет асинхронно отправлять запросы серверу и получать результаты в виде текста. А решение о том, что запрашивать, как обрабатывать запрос на стороне сервера и что возвращать клиенту, возлагается на разработчика.

Хотя современные браузеры предоставляют широкую поддержку объекта XMLHttpRequest, существуют тонкие различия в способе получения к нему доступа. В некоторых браузерах, включая Internet Explorer 7, Firefox, Safari и Opera, объект XMLHttpRequest реализован в виде собственного объекта JavaScript. В версиях, предшествующих Internet Explorer 7, он реализован как объект ActiveX. Вследствие этих различий код JavaScript должен быть достаточно интеллектуальным, чтобы использовать правильный подход при создании экземпляра XMLHttpRequest. Ниже приведен клиентский код JavaScript, который Microsoft применяет при решении этой задачи для клиентской функции обратного вызова:

Отправка запроса

Для отправки запроса с помощью объекта XMLHttpRequest будут использоваться два метода: open() и send().

Метод open() устанавливает вызов — он определяет запрос, который требуется отправить серверу. У него есть два обязательных параметра — тип команды HTTP (GET, POST или PUT) и URL-адрес. Например:

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

По умолчанию все запросы, выполняемые с помощью объекта XMLHttpRequest, являются асинхронными, И в основном нет причин изменять это поведение. Если решите выполнять вызов синхронно, с тем же успехом можно инициировать обратную отправку — в конце концов, пользователь будет неспособен сделать что-либо, пока страница заморожена и ожидает ответа. Отсутствие асинхронности означает отсутствие Ajax.

Метод send() отправляет запрос. Если запрос является асинхронным, он выполняет возврат немедленно:

Метод send() принимает единственный необязательный строковый параметр. Его можно применять для предоставления дополнительной информации, отправляемой с запросом, такой как значения, которые отправляются с запросом POST.

Обработка ответа

Очевидно, что был упущен один нюанс. Мы выяснили, как отправить запрос, но как обработать ответ? Секрет в том, чтобы присоединить обработчик события, используя свойство onreadystatechange. Это свойство указывает на клиентскую функцию JavaScript, которая вызывается, когда запрос завершен и данные доступны:

Конечно, обработчик события должен быть присоединен до вызова метода send() для запуска запроса.

Когда ответ возвращен с сервера и функция инициирована, необходимую информацию можно извлечь из объекта xmlRequest через свойства responseText и responseXML. Свойство responseText предоставляет все содержимое как одну длинную строку. Свойство responseXML возвращает содержимое в виде дерева узловых объектов.

Несмотря на то что название Ajax подразумевает XML-содержимое, из сервера можно также вернуть что-нибудь другое, в том числе простой текст. Например, если сервер возвращает единственный фрагмент данных, нет никакого смысла помещать его в полный XML-документ.

Константы

Следующие константы объекта XMLHttpRequest определяют возможные значения свойства readyState:

Значение Константа Описание
UNSENT Объект XMLHttpRequest был создан, метод open() объекта не вызывался.
1 OPENED Метод open() объекта был вызван. Во время этого состояния заголовки запросов могут быть установлены с помощью метода setRequestHeader() и метод send() может быть вызван, который инициирует отправку запроса.
2 HEADERS_RECEIVED Метод send() объекта был вызван, заголовки и статус доступны.
3 Происходит загрузка тела ответа сервера. Если значение свойства responseType соответствует значению «text» или пустой строке, то значение свойства responseText будет содержать частичные данные.
4 DONE Операция завершена. Это может означать, что передача данных была завершена успешно или не удалась.

Ошибка в скрипте с другого источника

Есть правило: скрипты с одного сайта не могут получить доступ к содержимому другого сайта. Например, скрипт с не может прочитать почту пользователя на .

Или, если быть более точным, один источник (домен/порт/протокол) не может получить доступ к содержимому с другого источника. Даже поддомен или просто другой порт будут считаться разными источниками, не имеющими доступа друг к другу.

Это правило также касается ресурсов с других доменов.

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

Для примера давайте возьмём мини-скрипт , который состоит из одного-единственного вызова функции, которой не существует:

//  error.js
noSuchFunction();

Теперь загрузим этот скрипт с того же сайта, на котором он лежит:

<script>
window.onerror = function(message, url, line, col, errorObj) {
  alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="/article/onload-onerror/crossorigin/error.js"></script>

Мы видим нормальный отчёт об ошибке:

А теперь загрузим этот же скрипт с другого домена:

<script>
window.onerror = function(message, url, line, col, errorObj) {
  alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>

Отчёт отличается:

Детали отчёта могут варьироваться в зависимости от браузера, но основная идея остаётся неизменной: любая информация о внутреннем устройстве скрипта, включая стек ошибки, спрятана. Именно потому, что скрипт загружен с другого домена.

Зачем нам могут быть нужны детали ошибки?

Существует много сервисов (и мы можем сделать наш собственный), которые обрабатывают глобальные ошибки при помощи , сохраняют отчёт о них и предоставляют доступ к этому отчёту для анализа. Это здорово, потому что мы можем увидеть реальные ошибки, которые случились у наших пользователей. Но если скрипт — с другого домена, то информации об ошибках в нём почти нет, как мы только что видели.

Похожая кросс-доменная политика (CORS) внедрена и в отношении других ресурсов.

Чтобы разрешить кросс-доменный доступ, нам нужно поставить тегу атрибут , и, кроме того, удалённый сервер должен поставить специальные заголовки.

Существует три уровня кросс-доменного доступа:

  1. Атрибут отсутствует — доступ запрещён.
  2. — доступ разрешён, если сервер отвечает с заголовком со значениями или наш домен. Браузер не отправляет авторизационную информацию и куки на удалённый сервер.
  3. — доступ разрешён, если сервер отвечает с заголовками со значением наш домен и . Браузер отправляет авторизационную информацию и куки на удалённый сервер.

В нашем случае атрибут отсутствовал. Поэтому кросс-доменный доступ был запрещён. Давайте добавим его.

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

Если куки нас не волнуют, тогда смело выбираем :

<script>
window.onerror = function(message, url, line, col, errorObj) {
  alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script *!*crossorigin="anonymous"*/!* src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>

Теперь при условии, что сервер предоставил заголовок , всё хорошо. У нас есть полный отчёт по ошибкам.

FormData

Современные браузеры, исключая IE9- (впрочем, есть полифилл), поддерживают встроенный объект FormData, который может кодировать формы для отправки на сервер.

Это  бывает очень удобно. Например:

<form name="person"> 
<input name="name" value="Виктор"> 
<input name="surname" value="Цой"> 
</form> 
<script>
  // создать объект для формы 
var formData = new FormData(document.forms.person); 
// добавить к пересылке ещё пару ключ - значение 
formData.append("patronym", "Робертович"); // отослать 
var xhr = new XMLHttpRequest(); xhr.open("POST", "/url"); 
xhr.send(formData); </script>

Этот код отправит на сервер форму с полями name, surname и patronym.

Интерфейс:

  • Конструктор new FormData() вызывается либо без аргументов, либо с DOM-элементом формы.
  • Метод formData.append(name, value) добавляет данные к форме.

Объект formData можно сразу отсылать, интеграция FormData с XMLHttpRequest встроена в браузер. Кодировка при этом будет multipart/form-data.

«Непростые» запросы

В кросс-доменном можно указать не только , но и любой другой метод, например , .

Когда-то никто и не думал, что страница сможет сделать такие запросы. Поэтому ряд веб-сервисов написаны в предположении, что «если метод – нестандартный, то это не браузер». Некоторые веб-сервисы даже учитывают это при проверке прав доступа.

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

  • Если метод – не GET / POST / HEAD.
  • Если заголовок имеет значение отличное от , или , например .
  • Если устанавливаются другие HTTP-заголовки, кроме , , .

…Любое из условий выше ведёт к тому, что браузер сделает два HTTP-запроса.

Первый запрос называется «предзапрос» (английский термин «preflight»). Браузер делает его целиком по своей инициативе, из JavaScript мы о нём ничего не знаем, хотя можем увидеть в инструментах разработчика.

Этот запрос использует метод . Он не содержит тела и содержит название желаемого метода в заголовке , а если добавлены особые заголовки, то и их тоже – в .

Его задача – спросить сервер, разрешает ли он использовать выбранный метод и заголовки.

На этот запрос сервер должен ответить статусом 200, без тела ответа, указав заголовки и, при необходимости, .

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

Давайте рассмотрим предзапрос на конкретном примере.

Рассмотрим запрос , который используется в протоколе WebDAV для управления файлами через HTTP:

Этот запрос «непростой» по двум причинам (достаточно было бы одной из них):

  1. Метод .
  2. Заголовок .

Поэтому браузер, по своей инициативе, шлёт предварительный запрос :

Обратим внимание на детали:

  • Адрес – тот же, что и у основного запроса: .
  • Стандартные заголовки запроса , , присутствуют.
  • Кросс-доменные специальные заголовки запроса:
    • – домен, с которого сделан запрос.
    • – желаемый метод.
    • – желаемый «непростой» заголовок.

На этот запрос сервер должен ответить статусом 200, указав заголовки и .

Но в протоколе WebDav разрешены многие методы и заголовки, которые имеет смысл сразу перечислить в ответе:

Ответ должен быть без тела, то есть только заголовки.

Браузер видит, что метод – в числе разрешённых и заголовок – тоже, и дальше он шлёт уже основной запрос.

При этом ответ на предзапрос он закэширует на 86400 сек (сутки), так что последующие аналогичные вызовы сразу отправят основной запрос, без .

Основной запрос браузер выполняет уже в «обычном» кросс-доменном режиме:

Ответ сервера, согласно спецификации , может быть примерно таким:

Так как содержит правильный домен, то браузер вызовет и запрос будет завершён.

История

Впервые был разработан компанией 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 и в других.

Основы

XMLHttpRequest имеет два режима работы: синхронный и асинхронный.

Сначала рассмотрим асинхронный, так как в большинстве случаев используется именно он.

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

  1. Создать .

  2. Инициализировать его.

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

    • – HTTP-метод. Обычно это или .
    • – URL, куда отправляется запрос: строка, может быть и объект URL.
    • – если указать , тогда запрос будет выполнен синхронно, это мы рассмотрим чуть позже.
    • , – логин и пароль для базовой HTTP-авторизации (если требуется).

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

  3. Послать запрос.

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

    Некоторые типы запросов, такие как , не имеют тела. А некоторые, как, например, , используют , чтобы отправлять данные на сервер. Мы позже увидим примеры.

  4. Слушать события на , чтобы получить ответ.

    Три наиболее используемых события:

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

Вот полный пример. Код ниже загружает с сервера и сообщает о прогрессе:

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

Код состояния HTTP (число): , , и так далее, может быть в случае, если ошибка не связана с HTTP.
Сообщение о состоянии ответа HTTP (строка): обычно для , для , для , и так далее.
(в старом коде может встречаться как )
Тело ответа сервера.

Мы можем также указать таймаут – промежуток времени, который мы готовы ждать ответ:

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

URL с параметрами

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

§Real-Time Notifications and Delivery

XHR enables a simple and efficient way to synchronize client updates
with the server: whenever necessary, an XHR request is dispatched by the
client to update the appropriate data on the server. However, the same
problem, but in reverse, is much harder. If data is updated on the
server, how does the server notify the client?

HTTP does not provide any way for the server to initiate a new
connection to the client. As a result, to receive real-time
notifications, the client must either poll the server for updates or
leverage a streaming transport to allow the server to push new
notifications as they become available. Unfortunately, as we saw in the
preceding section, support for XHR streaming is limited, which leaves us
with XHR polling.

«Real-time» has different meanings for different applications: some
applications demand submillisecond overhead, while others may be just
fine with delays measured in minutes. To determine the optimal
transport, first define clear latency and overhead targets for your
application!

Отправляем данные на сервер

Обыч­но, что­бы отпра­вить дан­ные на сер­вер, нуж­но делать запрос. Вы нажи­ма­е­те кноп­ку на стра­ни­це, бра­у­зер ухо­дит думать, ждёт отве­та сер­ве­ра и рису­ет вам новую стра­ни­цу в соот­вет­ствии с этим отве­том. Гру­бо гово­ря, запрос на сер­вер застав­ля­ет вашу стра­ни­цу перезагружаться.

К сча­стью, инже­не­ры дав­но при­ду­ма­ли, как отправ­лять дан­ные на сер­вер, не пере­за­гру­жая стра­ни­цу. Для это­го исполь­зу­ют JavaScript.

Что­бы отпра­вить запрос, нам пона­до­бит­ся встро­ен­ный объ­ект XMLHttpRequest(). Вот как мы вво­дим его в повествование:

// создаём новый экземпляр запроса XHR
let xhr = new XMLHttpRequest();

Для запро­са нам нуж­но знать адрес, куда будем отправ­лять наш JSON — это и есть адрес наше­го скрип­та, кото­рый мы напи­шем поз­же. Мы будем писать его на PHP, поэто­му зара­нее можем при­ду­мать ему имя и адрес, где он будет лежать: http://mihailmaximov.ru/projects/json/json.php.

// адрес, куда мы отправим нашу JSON-строку
url = «http://mihailmaximov.ru/projects/json/json.php»;

Когда мы зна­ем адрес, мы можем открыть соеди­не­ние, что­бы сер­вер был готов при­нять наши дан­ные. Это зна­чит, что мы пока ниче­го цен­но­го туда не посы­ла­ем, а про­сто пре­ду­пре­жда­ем сер­вер, что ско­ро что-то прилетит:

// открываем соединение. url — это переменная с нашим адресом
xhr.open(«POST», url, true);

Теперь напи­шем заго­ло­вок запро­са, что­бы сер­вер пони­мал, какие дан­ные мы ему при­шлём и как ему их обра­ба­ты­вать. Так как у нас JSON, то это и про­пи­шем в заголовке:

 // устанавливаем заголовок — выбираем тип контента, который отправится на сервер, в нашем случае мы явно пишем, что это JSON
setRequestHeader(«Content-Type», «application/json»);

Чуть ниже сра­зу про­пи­шем пове­де­ние скрип­та на слу­чай отве­та сер­ве­ра. Сер­вер дол­жен обра­бо­тать наши дан­ные, вер­нуть ответ, а мы долж­ны этот ответ пой­мать и выве­сти на страницу:

Послед­нее, что нам оста­лось сде­лать, — выта­щить наши вве­дён­ные дан­ные из полей, собрать из них JSON и отпра­вить на сервер:

 // преобразуем наши данные JSON в строку
      var data = JSON.stringify({ «name»: name.value, «lastname»: lastname.value });
      // когда всё готово, отправляем JSON на сервер
      xhr.send(data);
Готовый скрипт на странице

Получение нового содержимого

Другой ситуацией, в которой можно использовать объект XMLHttpRequest, будет загрузка нового содержимого в страницу. Например, новостная статья может сопровождаться несколькими фотографиями, но одновременно отображается только одна из них. Чтобы отобразить другую фотографию, пользователь нажимает соответствующую кнопку, а JavaScript-код получает ее и вставляет вместо предыдущей. Этот же способ можно использовать для показа изображений в слайд-шоу.

Пример такого слайд-шоу показан на рисунке ниже:

Содержимое этой страницы состоит из нескольких отдельных слайдов. Управление слайдами осуществляется щелчком по ссылкам «Пред» и «След», в результате чего загружается новое изображение со своей подписью. Запрос нового содержимого осуществляется посредством объекта XMLHttpRequest.

Для использования дизайна, подобного показанному, может быть несколько причин. При умелой реализации этот метод может позволить удерживать под контролем большие объемы содержимого, которое всегда готово для просмотра, но не перегружает страницу.

Лучшим способом реализации страницы такого типа будет использование объекта XMLHttpRequest. Таким образом, страница может запрашивать новое содержимое и обновлять только часть окна, не вызывая обновления всей страницы. А полные обновления плохи тем, что расходуют трафик, вызывают мигание страницы и заставляют пользователя прокручивать страницу обратно вверх. Все это может казаться мелочами, но такие мелочи отличают профессиональные, отполированные страницы от неуклюжих любительских.

Для создания примера, показанного на рисунке, сначала нам нужно выделить место для динамического содержимого. Для этого мы используем элемент <div>, который создает нам рамку с золотистым обрамлением и двумя ссылками внизу:

Ссылки вызывают функцию previousSlide() или nextSlide() в зависимости от направления просмотра слайдов. В обеих функциях используется счетчик, начальное значение которого равно 0, увеличивается до 5 и начинает новый цикл со значения 1. Код функций nextSlide() и previousSlide() выглядит следующим образом:

Обе функции используют еще одну функцию, goToNewSlide(), которая в действительности и выводит новое изображение:

Последний шаг в клиентской части — это скопировать полученные данные и элемент <div>, который отображает текущий слайд:

Серверный код получает номер слайда и возвращает необходимую разметку:

Чтобы придать этому примеру больше шика, изображения можно менять, используя эффект перехода. Например, новое изображение может постепенно проявляться, в то время как старое постепенно исчезает. Это одно из достоинств динамических страниц, использующих объект XMLHttpRequest — они могут полностью управлять способом представления содержимого.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector