Onload

Обмен сообщениями между окнами

Интерфейс позволяет окнам общаться между собой независимо от их происхождения.

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

Интерфейс имеет две части.

Окно, которое хочет отправить сообщение, должно вызвать метод postMessage окна получателя. Другими словами, если мы хотим отправить сообщение в окно , тогда нам следует вызвать .

Аргументы:

Данные для отправки. Может быть любым объектом, данные клонируются с использованием «алгоритма структурированного клонирования». IE поддерживает только строки, поэтому мы должны использовать метод на сложных объектах, чтобы поддержать этот браузер.
Определяет источник для окна-получателя, только окно с данного источника имеет право получить сообщение.

Указание является мерой безопасности. Как мы помним, если окно (получатель) происходит из другого источника, мы из окна-отправителя не можем прочитать его . Таким образом, мы не можем быть уверены, какой сайт открыт в заданном окне прямо сейчас: пользователь мог перейти куда-то, окно-отправитель не может это знать.

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

Особенно это важно, если данные конфиденциальные

Например, здесь получит сообщения только в том случае, если в нём открыт документ из источника :

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

Чтобы получать сообщения, окно-получатель должно иметь обработчик события (сообщение). Оно срабатывает, когда был вызван метод (и проверка пройдена успешно).

Объект события имеет специфичные свойства:

Данные из .
Источник отправителя, например, .
Ссылка на окно-отправитель. Можно сразу отправить что-то в ответ, вызвав .

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

Вот пример:

Полный пример:

Результат
iframe.html
index.html

Без задержек

Между и событием не существует задержки. Событие происходит синхронно, быстрее, чем .

Живой и динамичный сайт

Трудно представить создание современного динамичного сайта без применения JavaScript и onload. Function GoPage() — это не просто определение состояния браузера и перерасчет координат элементов страницы (в примере выше).

Function GoPage — это вызов сервера «InitXML( …» для принятия важных решений и «продолжения отношений».

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

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

Если рассматривать onload как приход посетителя, то ситуация переходит из события страницы в событие «взаимодействия» между посетителем сайта (постоянным клиентом), в их отношения в течение времени.

Crossorigin policy

There’s a rule: scripts from one site can’t access contents of the other site. So, e.g. a script at can’t read the user’s mailbox at .

Or, to be more precise, one origin (domain/port/protocol triplet) can’t access the content from another one. So even if we have a subdomain, or just another port, these are different origins with no access to each other.

This rule also affects resources from other domains.

If we’re using a script from another domain, and there’s an error in it, we can’t get error details.

For example, let’s take a script that consists of a single (bad) function call:

Now load it from the same site where it’s located:

We can see a good error report, like this:

Now let’s load the same script from another domain:

The report is different, like this:

Details may vary depending on the browser, but the idea is the same: any information about the internals of a script, including error stack traces, is hidden. Exactly because it’s from another domain.

Why do we need error details?

There are many services (and we can build our own) that listen for global errors using , save errors and provide an interface to access and analyze them. That’s great, as we can see real errors, triggered by our users. But if a script comes from another origin, then there’s not much information about errors in it, as we’ve just seen.

Similar cross-origin policy (CORS) is enforced for other types of resources as well.

To allow cross-origin access, the tag needs to have the attribute, plus the remote server must provide special headers.

There are three levels of cross-origin access:

  1. No attribute – access prohibited.
  2. – access allowed if the server responds with the header with or our origin. Browser does not send authorization information and cookies to remote server.
  3. – access allowed if the server sends back the header with our origin and . Browser sends authorization information and cookies to remote server.

Please note:

You can read more about cross-origin access in the chapter Fetch: Cross-Origin Requests. It describes the method for network requests, but the policy is exactly the same.

Such thing as “cookies” is out of our current scope, but you can read about them in the chapter Cookies, document.cookie.

In our case, we didn’t have any crossorigin attribute. So the cross-origin access was prohibited. Let’s add it.

We can choose between (no cookies sent, one server-side header needed) and (sends cookies too, two server-side headers needed).

If we don’t care about cookies, then is the way to go:

Now, assuming that the server provides an header, everything’s fine. We have the full error report.

Loading a script

Let’s say we need to load a third-party script and call a function that resides there.

We can load it dynamically, like this:

…But how to run the function that is declared inside that script? We need to wait until the script loads, and only then we can call it.

Please note:

For our own scripts we could use JavaScript modules here, but they are not widely adopted by third-party libraries.

The main helper is the event. It triggers after the script was loaded and executed.

For instance:

So in we can use script variables, run functions etc.

…And what if the loading failed? For instance, there’s no such script (error 404) or the server is down (unavailable).

Errors that occur during the loading of the script can be tracked in an event.

For instance, let’s request a script that doesn’t exist:

Please note that we can’t get HTTP error details here. We don’t know if it was an error 404 or 500 or something else. Just that the loading failed.

Important:

Events / track only the loading itself.

Errors that may occur during script processing and execution are out of scope for these events. That is: if a script loaded successfully, then triggers, even if it has programming errors in it. To track script errors, one can use global handler.

Стили

Создаем класс  modalDialog и начинаем формировать внешний вид:

.modalDialog {
	position: fixed;
	font-family: Arial, Helvetica, sans-serif;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	background: rgba(0,0,0,0.8);
	z-index: 99999;
	-webkit-transition: opacity 400ms ease-in;
	-moz-transition: opacity 400ms ease-in;
	transition: opacity 400ms ease-in;
	display: none;
	pointer-events: none;
}

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

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

В завершении устанавливаем переходы для вывода нашего модального окна и скрываем его в неактивном состоянии.

Может быть вы не знаете свойство pointer-events, но оно позволяет контролировать как элементы будут реагировать на нажатие кнопки мыши. Мы устанавливаем значение его значение для класса modalDialog, так как ссылка не должна реагировать на нажатие кнопки мыши когда активен псевдо класс “:target”.

Теперь добавляем псевдо класс :target и стили для модального окна.

.modalDialog:target {
	display: block;
	pointer-events: auto;
}

.modalDialog > div {
	width: 400px;
	position: relative;
	margin: 10% auto;
	padding: 5px 20px 13px 20px;
	border-radius: 10px;
	background: #fff;
	background: -moz-linear-gradient(#fff, #999);
	background: -webkit-linear-gradient(#fff, #999);
	background: -o-linear-gradient(#fff, #999);
}

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

Мы определяем ширину модального окна и положение на странице. Также определяем градиент для фона и скругленные углы.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Почитать больше о кросс-доменных доступах вы можете в главе Fetch: запросы на другие сайты. Там описан метод для сетевых запросов, но политика там точно такая же.

Такое понятие как «куки» (cookies) не рассматривается в текущей главе, но вы можете почитать о них в главе Куки, document.cookie.

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

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

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

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

Контроль безопасности

Кросс-доменные запросы проходят специальный контроль безопасности, цель которого – не дать злым хакерам завоевать интернет.

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

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

Как сможет этим воспользоваться злой хакер?

Он сделает свой сайт, например и заманит туда посетителя (а может посетитель попадёт на «злонамеренную» страницу и по ошибке – не так важно). Когда посетитель зайдёт на , он автоматически запустит JS-скрипт на странице

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

Когда посетитель зайдёт на , он автоматически запустит JS-скрипт на странице. Этот скрипт сделает HTTP-запрос на почтовый сервер, к примеру, . А ведь обычно HTTP-запросы идут с куками посетителя и другими авторизующими заголовками.

Поэтому хакер сможет написать на код, который, сделав GET-запрос на , получит информацию из почтового ящика посетителя. Проанализирует её, сделает ещё пачку POST-запросов для отправки писем от имени посетителя. Затем настанет очередь онлайн-банка и так далее.

Спецификация CORS налагает специальные ограничения на запросы, которые призваны не допустить подобного апокалипсиса.

Запросы в ней делятся на два вида.

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

  1. : GET, POST или HEAD
  2. – только из списка:
  • со значением , или .

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

Принципиальная разница между ними заключается в том, что «простой» запрос можно сформировать и отправить на сервер и без XMLHttpRequest, например при помощи HTML-формы.

То есть, злой хакер на странице и до появления CORS мог отправить произвольный GET-запрос куда угодно. Например, если создать и добавить в документ элемент , то браузер сделает GET-запрос на этот URL.

Аналогично, злой хакер и ранее мог на своей странице объявить и, при помощи JavaScript, отправить HTML-форму с методом GET/POST и кодировкой . А значит, даже старый сервер наверняка предусматривает возможность таких атак и умеет от них защищаться.

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

Поэтому при посылке «непростых» запросов нужно специальным образом спросить у сервера, согласен ли он в принципе на подобные кросс-доменные запросы или нет? И, если сервер не ответит, что согласен – значит, нет.

В спецификации CORS, как мы увидим далее, есть много деталей, но все они объединены единым принципом: новые возможности доступны только с явного согласия сервера (по умолчанию – нет).

Example HTML code 3:

This example illustrates the use of the onload event for XMLDocument objects. Note that this example does not work in Google Chrome and Safari, because they do not support the onload event for XMLDocument objects.

Code ajax.js
<head><scripttype="text/javascript"src="ajax.js"></script><scripttype="text/javascript">var xmlDoc = null;

        function LoadXML () {
            xmlDoc = CreateXMLDocumentObject ();    // defined in ajax.js
if (!xmlDoc) {
                return;
            }

            var url = "large.xml";
            xmlDoc.async = true;

            if (xmlDoc.addEventListener) {  // Firefox, Opera, Google Chrome and Safari
                xmlDoc.addEventListener("load", OnLoadXML, false);
            }
            else {
                xmlDoc.onreadystatechange = OnStateChange;
            }

            xmlDoc.load (url);
        }

        function OnLoadXML () {
            LoadingFinished ();
        }

        function OnStateChange () {
            var output = document.getElementById ("output");
            switch (xmlDoc.readyState) {
            case1:
                output.innerHTML += "The load method was called, but no data has been received yet.<br/>";
                break;
            case2:
                output.innerHTML += "A part of the data has been loaded, but the document object model (DOM) is not yet available.<br/>";
                break;
            case3:
                output.innerHTML += "The document object model has been built from the received data and it is available.<br/>";
                break;
            case4:
                LoadingFinished ();
                break;
            };
        }

        function LoadingFinished () {
            var output = document.getElementById ("output");
            output.innerHTML += "All data has been loaded, the operation is finished:<br/>";

            var errorMsg = null;
            if (xmlDoc.parseError && xmlDoc.parseError.errorCode != ) {
                errorMsg = "XML Parsing Error: <span style='color:red'>" + xmlDoc.parseError.reason
                          + " at line " + xmlDoc.parseError.line
                          + " at position " + xmlDoc.parseError.linepos
                          + "</span><br/>";
            }
            else {
                if (xmlDoc.documentElement) {
                    if (xmlDoc.documentElement.nodeName == "parsererror") {
                        errorMsg = "<span style='color:red'>" + xmlDoc.documentElement.childNodesnodeValue + "</span><br/>";
                    }
                }
            }
            if (errorMsg) {
                output.innerHTML += errorMsg;
            }
            else {
                output.innerHTML += "<span style='color:blue'>The XML is valid.</span><br/>";
            }
        }
    </script></head><body><buttononclick="LoadXML ()">Analyze the loading process of an XML</button><br/><br/><divid="output"style="width:420px; height:200px; overflow:auto; border:1px solid #000000; background-color:#f5e4b1;"></div></body>

Did you find this example helpful?

yes
no

Проблема логики использования события onload

Посетитель приходит на сайт, страница загружается, срабатывает событие onload, и выполняются все подготовительные действия. Логика работы после отработки onload зависит от логики сайта и его функционального назначения.

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

Сайт поисковой системы может восстановить последнюю выборку для своего клиента и предложить описание своего функционала для нового посетителя.

Нет никакой гарантии, что завсегдатай сайта или новый посетитель не выберет обновление страницы. А это тоже событие onload, и JavaScript функции придется «уметь» различать первоначальную загрузку страницы от ее обновления. Это не большая проблема в программировании, но может составлять трудности для формирования правильной логики работы сайта в целом.

async

Атрибут означает, что скрипт абсолютно независим:

  • Страница не ждёт асинхронных скриптов, содержимое обрабатывается и отображается.
  • Событие и асинхронные скрипты не ждут друг друга:
    • может произойти как до асинхронного скрипта (если асинхронный скрипт завершит загрузку после того, как страница будет готова),
    • …так и после асинхронного скрипта (если он короткий или уже содержится в HTTP-кеше)
  • Остальные скрипты не ждут , и скрипты c не ждут другие скрипты.

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

  1. Содержимое страницы отображается сразу же : его не блокирует.
  2. может произойти как до, так и после , никаких гарантий нет.
  3. Асинхронные скрипты не ждут друг друга. Меньший скрипт идёт вторым, но скорее всего загрузится раньше , поэтому и запустится первым. То есть, скрипты выполняются в порядке загрузки.

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

readyState

В заключение
занятия отметим свойство

document.readyState

которое в момент
загрузки HTML-документа принимает
следующие значения:

  • «loading»
    – документ в процессе загрузки;

  • «interactive»
    – документ был полностью прочитан (парсинг документа завершен);

  • «complete»
    – документ был полностью прочитан и все ресурсы (изображения, стили и т.п.)
    тоже загружены.

В ряде случаев
это свойство бывает весьма полезно. Например, мы вызываем функцию, но не
уверены, что DOM-дерево
полностью построено. Поэтому, делаем такую проверку:

removeImage();
function removeImage() {
     if(document.readyState == "loading") {
          console.log("документ грузится, вешаем обработчик");
          document.addEventListener("DOMContentLoaded", removeImage);
     }
     else {
          console.log("удаляем изображение");
          document.body.remove(image);
     }
}

По аналогии
могут быть обработаны и остальные свойства.

Для полноты картины
пару слов о событии readystatechange, которое появилось до событий

DOMContentLoaded, load, unload, beforeunload

и в старых версиях
JavaScript процесс
загрузки документа контролировался через него. Например, так:

document.addEventListener('readystatechange', function() {
         console.log(document.readyState);
});

Теперь при
обновлении страницы мы можем увидеть изменение состояний свойства document.readyState в процессе
загрузки. Однако такой механизм отслеживания ушел в прошлое и сейчас уже нет смысла
о нем подробно говорить.

Итак, на этом
занятии мы с вами рассмотрели события

DOMContentLoaded,
load, unload, beforeunload

и поговорили о свойстве

document.readyState

которое
дополняет работу с этими событиями.

Видео по теме

JavaScipt (DOM) #1: объектная модель документа DOM и BOM

JavaScipt (DOM) #2: навигация по DOM — parentNode, nextSibling, previousSibling, chidNodes

JavaScipt (DOM) #3: методы поиска элементов в DOM: querySelector, querySelectorAll, getElementById

JavaScipt (DOM) #4: свойства DOM-узлов: nodeName, innerHTML, outerHTML, data, textContent, hidden

JavaScipt (DOM) #5: работа с нестандартными свойствами DOM-элементов: getAttribute, setAttribute, dataset

JavaScipt (DOM) #6: создание и добавление элементов DOM createElement, append, remove, insertAdjacentHTML

JavaScipt (DOM) #7: управление стилями — className, style, classList, getComputedStyle

JavaScipt (DOM) #8: метрики — clientWidth, scrollTop, scrollHeight, offsetLeft, offsetTop, clientLeft

JavaScipt (DOM) #9: HTML-документ: размеры (clientWidth, innerWidth), положение (pageYOffset, scrollBy)

JavaScipt (DOM) #10: расположение элементов — fixed, absolute, getBoundingClientRect, elementFromPoint

JavaScipt (DOM) #11: обработчики событий: onclick, addEventListener, removeEventListener, event

JavaScipt (DOM) #12: погружение и всплытие событий: stopPropagation, stopImmediatePropagation, eventPhase

JavaScipt (DOM) #13: делегирование событий, отмена действия браузера по умолчанию — preventDefault

JavaScipt (DOM) #14: события мыши mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter

JavaScipt (DOM) #15: события клавиатуры keydown, keyup, событие скроллинга scroll

JavaScipt (DOM) #16: навигация и обработка элементов форм (form) — document.forms, form.elements

JavaScipt (DOM) #17: фокусировка — focus, blur, focusin, focusout, tabindex, activeElement

JavaScipt (DOM) #18: события change, input, cut, copy, paste, submit элементов input и select

JavaScipt (DOM) #19: события при загрузке — DOMContentLoaded, load, unload, beforeunload, readyState

JavaScipt (DOM) #20: события load, error; атрибуты async, defer тега script

JavaScipt (DOM) #21: пример предзагрузки изображений с помощью javascript

JavaScipt (DOM) #22: пример создания начала игры арканоид

Пример 3. Передача синхронного AJAX запроса на сервер с помощью метода POST

В этом примере данные на сервер будем передавать с помощью метода POST (в теле HTTP-запроса). В методе POST данные (параметры) передаются не в составе URL (метод GET), а в теле, которое мы посылаем серверу через . Т.е. для того чтобы передать данные с помощью POST, мы их должны поместить в качестве параметра методу . Кроме того, при отправке данных с помощью POST необходимо также указать заголовок Content-Type, содержащий кодировку с помощью которой мы зашифровали данные. Это необходимо сделать для того чтобы сервер знал как обработать (расшифровать), пришедшие к нему данные (запрос).

<html lang="ru">
  <head>
    <meta charset="utf-8">
    <title>JavaScript AJAX</title>
    <style>
      span {
        font-weight: bold;
        color: red;
      }
    </style>
  </head>
  <body>
    <p>Введите имя и нажмите на кнопку "Получить...".</p> 
    <input id="nameUser" type="text" placeholder="Введите имя">
    <input id="button" type="button" value="Получить ответ с сервера">
    <p>Ответ (AJAX): <span id="answer"></span></p>
    <script src="script.js"></script>
  </body>
</html> 
// получить элемент, имеющий id="button"
var button = document.getElementById("button");
// подпишемся на событие click элемента 
button.addEventListener("click",function() {
  // создадим объект XMLHttpRequest
  var request = new XMLHttpRequest();
  // параметры запроса
  var params = 'name=' + encodeURIComponent(document.getElementById("nameUser").value);
  // настраиваем запрос: POST - метод, ajaxpost.php - URL-адрес, по которому посылается запрос, false - синхронный запрос
  request.open('POST','ajaxpost.php',false);
  // указываем заголовок Content-Type, содержащий кодировку 
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
  // отправляем данные на сервер с помощью метода send
  request.send(params);
  // если статус ответа 200 (OK) то
  if (request.status==200) {
    // выведем в элемент, имеющий id="answer", ответ сервера
    document.getElementById("answer").innerHTML = request.responseText;
  }	
})
<?php
// если в ассоциативном массиве $_POST существует ключ name
if (isset($_POST)) {
  // присвоим переменной $name значение из ассоциативного массива POST соответсвующее ключу name
  $name = $_POST;
  // выведем строку (ответ сервера)
  echo "Привет, ".$name."!";
}     
?>

Запрос данных JSON и обработка ответа

В случае с JSON процесс аналогичен запросу XML.
Основное отличие заключаются в настройке параметра на определенное значение, анализе данных и добавлении сокращенного метода, который может использоваться в качестве альтернативы типичному запросу Ajax jQuery.
Ниже рассматриваются все эти различия.

В листинге 6 приведен пример файла JSON, содержащего те же данные, что и XML-файл из .
Цель состоит в том, чтобы с использованием этих данных получить тот же HTML-файл

Важно строго придерживаться JSON, так как любое отклонение будет отвергнуто с сообщением об ошибке обработки

Листинг 6.
Код JSON для примера запроса
{"content":
     {
     "header": "Improving Ajax Development with jQuery",
     "description": "It's no surprise that Ajax is a great way to enhance a web 
     application. However, sometimes the code that needs to be written can take more 
     time than traditional development techniques, especially when you're interacting 
     with dynamic server-side data sets. Luckily, with the introduction of jQuery there's 
     now a quicker and more robust way to write JavaScript and Ajax. The suite of Ajax 
     functions available through jQuery makes Ajax development much easier than the 
     past by allowing you to write less code and by lending additional methods and event 
     handlers to cover any situation. The amount of code that needs to be written with 
     jQuery is very minimal, even when developing complex functions, so development 
     is a lot faster. With these tools Ajax is becoming a more viable option when 
     developing a website or application, even on a tight deadline.",
     "sourceUrl": 
"http://articles.studiosedition.com/ibm/improving_ajax/ImprovingAjaxDevWithJQuery.zip"
     }
}

Для формирования запроса и анализа ответа JSON нужно настроить HTML как в примере XML, сначала вложив в него библиотеку jQuery, а затем включив свой специальный код в событие .
В Ajax-запросе, приведенном в листинге 7, есть новый параметр .
Его можно использовать для информирования jQuery о том, что ожидается ответ JSON, чтобы возвращался объект JavaScript, который будет легко разобрать.
За кулисами JQuery использует функцию , которая принимает правильно сформированную строку JSON и возвращает результат в объект JavaScript.
Это означает, что JQuery запрашивает данные JSON, преобразует их в объект JavaScript и возвращает в ответ объект JavaScript, так что вам не нужно ничего делать, кроме обращения к объекту.
Этот процесс избавляет от написания собственных функций и дополнительного кода.

Листинг 7.
Запрос и разбор JSON с помощью Ajax и jQuery
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Improving Ajax Development with jQuery</title>
<script type="text/javascript" 
src="https://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
     $.ajax({
          url: 'data/content.js',
          dataType: 'json',
          success: function(js) {
          $("body").append('<h1>'+ js.content.header+'</h1>');
          $("body").append('<p>'+ js.content.description+'</p>');
          $("body").append('<a href="'+ js.content.sourceUrl+'">Download the source</a>');
     },
     error: function(xhr, status, err) {
          // Обработка ошибок
     }
     });
});
</script>
</head>

<body>
</body>
</html>

Разбор JSON после преобразования в объект JavaScript ничем не отличается от доступа к свойствам и функциям любого объекта JavaScript с точечной записью.
В листинге 8 видно, что параметр события назван .
Такое имя позволяет легко определить, что это наш объект JavaScript.
Объект принимает структуру файла JSON, так что можно обратиться к объекту , а затем к , и внутри объекта .
HTML обрабатывается аналогично примеру XML путем применения простой разметки и добавления его к элементу HTML-страницы.

Для запроса JSON можно использовать и другой сокращенный метод, называемый , который загружает данные JSON с сервера с помощью метода .
Эквивалент предыдущего запроса JSON с применением метода представлен в листинге 8.

Листинг 8.
Запрос и разбор данных JSON с помощью метода getJSON
<script type="text/javascript">
$(document).ready(function(){
	$.getJSON('data/content.js', function(js) {
	$("body").append('<h1>'+ js.content.header+'</h1>');
    $("body").append('<p>'+ js.content.description+'</p>');
$("body").append('<a href="'+ js.content.sourceUrl+'">Download the source</a>');
	});
});
</script>

Основы

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

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

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

  1. Создать .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Adblock
detector