Javascript & Ajax


Содержание материала:

jQuery и Ajax

— это сокращение от «Asynchronous JavaScript and XML» (асинхронный JavaScript и XML), но в наши дни этот термин употребляется как самостоятельный, без приписывания ему какого-либо смысла в результате расшифровки названия.

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

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

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

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

Кратко об Ajax

Если вы новичок в Ajax, позвольте вкратце рассказать вам о том, что такое асинхронные запросы. Это важно знать, поскольку асинхронные запросы занимают в Ajax центральное место, а буква А в Ajax происходит от слова asynchronous.

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

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

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

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

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

Выполнение GET-запросов Ajax

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

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

Это те же элементы, которые использовались в предыдущих статьях, но они не распределены по рядам и из элементов div удален атрибут class. Эти изменения внесены исключительно для того, чтобы продемонстрировать, как осуществляется обработка элементов, загружаемых в документ. Никаких технических предпосылок, которые заставляли бы поступать именно так, нет. Обратите внимание на то, что это не полноценный HTML-документ, а всего лишь фрагмент.

Для тестирования всех приведенных ниже и в следующей статье примеров, вы должны сохранить оба этих файла на локальном сервере. Если вы еще не установили локальный сервер, рекомендую WAMP сервер EasyPHP.

Для включения этого фрагмента в основной HTML-документ мы можем воспользоваться поддержкой Ajax, предоставляемой jQuery. Возможно, вас удивляет использование такого подхода, однако мы используем его, поскольку он имитирует распространенную ситуацию, когда сложный документ или веб-приложение получают путем «сшивки» отдельных фрагментов содержимого, создаваемого различными системами.

Пример того, как это можно сделать, приведен ниже:

Здесь используется метод get(), которому передаются два аргумента. Первый из них — это URL-адрес, указывающий на документ, который мы хотим загрузить. В данном случае используется адрес flowers.html, который будет интерпретироваться как URL, заданный относительно URL-адреса, использующегося для загрузки основного документа.

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

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

В этом сценарии метод get() используется для загрузки HTML-страницы, однако точно так же с сервера могут быть загружены данные любой природы.

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

Обработка ответных данных сервера

Функция, выполняющаяся в случае успешного завершения запроса, принимает в качестве аргумента данные, отправленные сервером в ответ на запрос. В этом примере мы получаем содержимое файла flowers.html, представляющее собой HTML-фрагмент. Чтобы превратить этот фрагмент в объект, с которым можно работать средствами jQuery, мы передаем его функции $(), которая выполнит синтаксический анализ фрагмента и сгенерирует дерево объектов HTMLElement, как показано в примере ниже:

Как уже отмечалось, из элементов div были намеренно удалены атрибуты class. Теперь, как видите, мы восстанавливаем их с помощью стандартного метода addClass(). Передав данные функции $(), мы получаем от нее объект jQuery, с которым далее можем работать как с любым другим объектом. Мы добавляем элементы в документ с помощью методов slice() и appendTo().

Обратите внимание на то, что для выбора элементов div, сгенерированных на основе полученных от сервера данных, используется метод filter(). Дело в том, что в процессе синтаксического анализа символы перевода строки, введенные между элементами div в файле flowers.html для структурирования данных, jQuery воспринимает как текстовое содержимое и вставляет вместо них текстовые элементы. Чтобы этого избежать, необходимо либо проследить за тем, чтобы эти символы отсутствовали в запрашиваемом документе, либо удалить их, используя метод filter().

Повышение наглядности процесса загрузки

В нашем сценарии инструкции, запускающие Ajax-запрос, начинают выполняться, когда срабатывает событие ready. Это мешает увидеть различия между использованием Ajax и встроенных данных. Для повышения наглядности процесса загрузки добавим в документ кнопку и сделаем так, чтобы Ajax-запрос выполнялся лишь после того, как на этой кнопке будет выполнен щелчок. Вносимые изменения отражены в примере ниже:

Теперь документ flowers.html не будет загружаться до тех пор, пока на кнопке «Ajax» не будет выполнен щелчок, причем каждый последующий щелчок также будет приводить к добавлению в документ дополнительных элементов, как показано на рисунке:

Обратите внимание на вызов метода preventDefault() для объекта Event, который передается в обработчик событий. Это делается для того, чтобы отменить выполнение браузером действий, предусмотренных по умолчанию. Поскольку элемент button содержится внутри элемента form, действием по умолчанию является отправка формы на сервер.

Получение других типов данных

Возможности метода get() не ограничиваются работой только с HTML. Он позволяет получать с сервера данные любой природы. Особый интерес для нас представляет формат JSON, предоставляющий удобные возможности для обработки данных средствами jQuery.

В свое время, когда технология Ajax еще только начинала широко внедряться, предпочтительным форматом данных считался XML, и даже буква X в аббревиатуре «Ajax» обязана своим происхождением этому формату. Я не собираюсь подробно обсуждать XML и лишь замечу, что этот язык страдает избыточностью синтаксиса, трудно читается и требует относительно больших затрат времени и ресурсов для генерации и обработки данных.

В последние годы формат XML был заметно потеснен форматом JSON (JavaScript Object Notation), отличающимся простотой и исключительной приспособленностью для работы с JavaScript-кодом (о чем говорит уже само его название). Специально для этого примера я создал файл mydata.json и сохранил его вместе с файлом test.html на веб-сервере. Содержимое файла mydata.json представлено в примере ниже:

В этом файле содержатся данные для различных видов цветочной продукции, и несложно заметить, что форма представления данных JSON совпадает с формой представления данных, встраиваемых в JavaScript-код. Это и есть одна из причин, по которым формат JSON вытеснил XML в веб-приложениях.

Для загрузки и обработки этих данных с помощью Ajax можно использовать метод get(), как показано в примере ниже (здесь мы используем шаблоны данных, вам потребуется добавить ссылку на библиотеку jquery.tmpl.js):

В этом примере файл с данными JSON запрашивается с сервера после щелчка на кнопке. Полученные данные передаются функции так, как если бы это был обычный HTML-фрагмент. Для обработки данных и генерации из них HTML-элементов используется подключаемый модуль шаблонов, а для вставки элементов в документ — методы slice() и appendTo(). Обратите внимание на то, что мы не предпринимаем никаких действий для того, чтобы преобразовать строку JSON в объект JavaScript — за нас это автоматически делает jQuery.

Некоторые веб-серверы (например Microsoft IIS 7.5) не возвращают содержимое браузеру, если не могут распознать расширение имени файла или формат данных. Чтобы этот пример работал с IIS, мне пришлось установить новое соответствие между расширением имени файла (.json) и MIME-типом данных в формате JSON (application/json). Пока я этого не сделал, веб-сервер IIS отвечал на мой запрос файла mydata.json сообщением с кодом 404 («Not Found»).

Передача данных GET-запросам

Данные могут пересылаться на сервер в составе GET-запросов, для отправки которых можно использовать методы get(), load(), getScript() и getJSON(). Соответствующий пример приведен ниже:

Предоставленные вами данные присоединяются к указанному URL-адресу в виде строки запроса. Это означает, что запрос имеет примерно следующий вид:

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

Выполнение POST-запросов Ajax

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

Серверный сценарий

Для этого раздела вам понадобится серверный сценарий, который будет получать данные, отправленные браузером с использованием HTTP-метода POST, выполнять простую операцию с использованием этих данных и генерировать ответ. Сценарий PHP (вы можете написать собственный сценарий для своей платформы) для этого раздела приведен в примере ниже:

Сохраните сценарий в файле phphandler.php. Этот сценарий обрабатывает данные, отправленные браузером, и генерирует ответ в формате JSON. Вообще говоря, можно было сделать так, чтобы этот сценарий возвращал HTML-данные, но формат JSON более компактен, и во многих случаях с ним проще работать.

Возвращаемый объект JSON чрезвычайно прост: он содержит общее количество единиц продукции, выбранной пользователем, и количество заказанных единиц по тем видам продукции, для которых оно указано. Таким образом, если выбрать одну астру, два нарцисса и две розы, то ответ в формате JSON, отправляемый сервером, будет выглядеть так:

Ранее формат JSON использовался нами для представления массива объектов, тогда как данный серверный сценарий возвращает одиночный объект, свойства которого соответствуют выбранным видам цветов. Свойство total содержит общее количество выбранных цветов. Должен признать, что подобного рода операции слишком просты для того, чтобы дать полное представление о возможностях обработки данных на сервере, но все же основной предмет нашего рассмотрения — Ajax, а не вопросы разработки серверных приложений.

Использование метода POST для отправки данных формы

Итак, теперь, когда вы уже имеете подготовленный сервер, можем приступить к использованию метода post() для оправки данных формы на сервер, как показано в примере ниже:

Этот пример кажется немного сложнее, чем он есть на самом деле. Мы начинаем с того, что используем метод getJSON() для получения файла mydata.json, содержащего описание цветочной продукции, после чего генерируем элементы с помощью шаблона данных и добавляем их в документ. В результате мы оказываемся на уже хорошо вам знакомой исходной позиции, которую, надеюсь, вы уже успели полюбить:

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

Первое, что делает обработчик — вызывает метод serialize() для элемента form. Это весьма полезный метод, который последовательно обрабатывает все элементы формы и создает строку, закодированную для передачи на сервер в качестве фрагмента URL-адреса. Для введенных мною значений метод serialize() генерирует следующую строку:

Я использую здесь метод serialize(), поскольку метод post() отправляет данные в закодированном для передачи в составе URL формате. Получив объект data, созданный на основе значений элементов input, мы вызываем метод post(), чтобы инициировать Ajax-запрос.

В качестве аргументов метод post() получает URL-адрес, по которому должны быть отправлены данные, подлежащие отправке, сами данные и функцию, которая должна быть вызвана в случае успешного выполнения запроса.

В этом примере получаемый от сервера ответ передается функции processServerResponse(). Сначала мы скрываем элементы div уровня ячеек, формирующие табличную компоновку страницы с использованием стилей CSS (они относятся к классу dcell), а затем отображаем те из них, которые соответствуют свойствам объекта JSON, полученного от сервера. Кроме того, мы используем шаблон данных для генерации разметки, отображающей общее количество выбранных единиц продукции. Это все можно было бы сделать с помощью клиента, но наша цель — научиться обрабатывать данные, возвращаемые POST-запросом Ajax. Результат показан на рисунке:

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

Указание ожидаемого типа данных

При использовании методов get() и post() библиотеке jQuery приходится определять тип данных, получаемых от сервера в ответ на запрос. Данными может быть все что угодно, начиная от HTML-кода и заканчивая файлами JavaScript. Для определения типа данных библиотека jQuery использует содержащуюся в ответе информацию, и в частности — заголовок Content-Type. Как правило, этого вполне достаточно, но иногда jQuery приходится оказывать небольшую помощь. Обычно необходимость в этом возникает из-за указания сервером неверного MIME-типа в ответе.

Можно изменить информацию, поставляемую сервером, и сообщить jQuery, какой тип данных ожидается, передавая методам get() и post() дополнительную информацию. Аргумент может принимать одно из следующих значений:

В примере ниже показано, как задать ожидаемый тип данных для метода post():

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

Ловушка при работе с Ajax

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

В этом сценарии определяется переменная elems, которая используется в функции обратного вызова Ajax для сохранения результата выполнения запроса к серверу. Полученные с сервера элементы добавляются в документ с помощью методов slice() и appendTo(). Если вы выполните этот пример, то увидите, что ни один из элементов не будет добавлен в документ, и вместо этого на консоли отобразится сообщение, конкретный текст которого зависит от типа браузера. Ниже приведено сообщение, отображаемое на консоли браузера Google Chrome:

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

Определяется переменная elems.

Получаемые с сервера данные присваиваются переменной elems.

Топ-пост этого месяца:  Как настроить чередование фонового цвета строк таблиц, списков и прочих Html элементов на сайте с

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

В действительности происходит следующее:

Определяется переменная elems.

Запускается асинхронный запрос к серверу.

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

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

В браузер поступают данные от сервера.

Данные обрабатываются и присваиваются переменной elems.

Причина появления сообщения об ошибке — вызов метода slice() для переменной в тот момент, когда она еще не содержит никаких элементов. Хуже всего то, что иногда этот код может работать правильно. Объясняется это тем, что Ajax-запрос выполняется настолько быстро, что к тому времени, когда начинается обработка переменной, в ней уже содержатся ожидаемые данные (обычно это наблюдается в тех случаях, когда данные кешируются браузером или когда между отправкой Ajax-запроса и попыткой обработки данных выполняются какие-либо сложные операции). Так что теперь, если ваш код будет вести себя подобным образом, вы уже знаете, что может быть причиной его необычного поведения.

Использование вспомогательных методов для работы с конкретными типами данных

Библиотека jQuery предоставляет три вспомогательных метода, которые делают работу с некоторыми типами данных более удобной. Некоторые из них мы рассмотрим далее.

Получение HTML-фрагментов

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

В этом сценарии мы вызываем метод load() для элемента, в который хотим вставить новые элементы, и передаем ему URL-адрес в качестве аргумента. Если запрос завершается успешно, а полученный от сервера ответ содержит действительный HTML-фрагмент, элементы вставляются в указанное место в документе, как показано на рисунке:

Вы видите, что все элементы из файла flowers.html добавлены в документ, как мы и хотели, но поскольку у них отсутствует атрибут class, то они не укладываются в табличную компоновку страницы, используемую в основном документе. Поэтому метод load() наиболее полезен в тех случаях, когда все элементы могут быть вставлены в одно место в документе без какой-либо дополнительной обработки.

Получение и выполнение сценариев

Метод getScript() загружает файл JavaScript, а затем выполняет содержащиеся в нем инструкции. Чтобы продемонстрировать работу этого метода, я создал файл myscript.js и сохранил его вместе с файлом test.html на своем веб-сервере. Содержимое этого файла представлено в примере ниже:

Эти инструкции генерируют три ряда элементов, описывающих цветы. Мы обошлись здесь без определения шаблонов и использовали циклы для генерации элементов (хотя, вообще говоря, следовало бы воспользоваться шаблонами данных).

Самое важное, что необходимо знать при работе со сценариям, — между инициализацией Ajax-запроса и выполнением инструкций сценария состояние документа может измениться. В примере ниже приведен сценарий из основного документа, в котором по-прежнему используется метод getScript(), но при этом, еще до завершения Ajax-запроса, модифицируется дерево DOM:

Здесь мы вызываем метод getScript() для основной функции $() и передаем ему в качестве аргумента URL-адрес файла, который хотим использовать. Если сервер способен предоставить указанный файл и этот файл содержит действительный JavaScript-код, то последний будет выполнен.

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

Используя метод getScript(), можно быстро получать запрашиваемую информацию, не доставляя пользователям неудобств, вызванных необходимостью ожидания ответа. Уточню свою мысль. Я вовсе не предлагаю вам использовать этот метод для выполнения каких-либо действий скрытно от пользователя и говорю лишь о том, что следует отодвигать на второй план загрузку и выполнение вполне законной функциональности, если она представляет для пользователей меньшую ценность, чем затрачиваемое на ее ожидание время.

В данном примере после запуска Ajax-запроса с помощью метода getScript() из документа удаляется элемент row2, для чего используется метод remove(). Данный элемент используется в файле myscript.js для вставки новых элементов. Эти элементы отбрасываются незаметным для пользователя образом, поскольку в документе селектору #row2 ничто не соответствует. Итоговый результат представлен на рисунке:

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

Получение данных в формате JSON

Для загрузки данных JSON с сервера предназначен метод getJSON(). Возможно, это наименее полезный из всех трех вспомогательных методов, поскольку он не делает с данными ничего сверх того, что делает базовый метод get().

XMLHttpRequest (AJAX) — отправка и обработка ответов http-запросов с помощью JavaScript.

В интерактивности — статические html сайты — это прошлое. Динамические с использованием CGI (или модулей сервера, например Apache) и баз данных, когда сервер при отправки формы формирует страницу и показывает ее после обновления — чуть современней, но все же во многих областях, где требуется практически сопостовимая с десктопными приложениями интерактивность — так же угасают. На смену приходят интерактивные функциональные программы, в полной мере взаимодействующие с пользователем; информация, полученная от сервера практически мгновенно отображается на экране без перезагрузке страницы. Речь я виду об AJAX’e, что в расшифровке «асинхронный JavaScript и XML» (термин ввел Джесс Гарретт). А если более подробно, то — «асинхронный JavaScript + CSS + DOM + XMLHttpRequest».

Методы объекта XMLHttpRequest

Все нижеизложанные методы и свойства — общие для Internet Explorer 5, Mozilla, Netscape 7, и соответственно, использовать их можно безопасно.

abort()
обрывает текущий запрос

getAllResponseHeaders()
возвращает полный набор заголовков ответа (названий и значений) в виде строки

getResponseHeader( )
возвращает строковое значение заголовка, название которого указано в параметре .

]]])
Присвоение параметров (метода, URL, и других) текущему запросу.

send( )
Посылает запрос

setRequestHeader( , )
Установка в отправляемом запросе заголовка со значением

Свойства объекта XMLHttpRequest

onreadystatechange
событие, возникающее при смене статуса объекта

readyState
значения статуса (integer), может принимать следующие значения: 0 = неинициализирован (uninitialized); 1 = «идет загрузка» (loading); 2 = «загружен» (loaded); 3 = «интерактивен» (interactive) 4 = «выполнен» (complete)

responseText
строка с возвращенными сервером данными

responseXML
DOM-совместимый объект-документ с возвращенными сервером данными

status
стандартный HTTP код статуса, например 404 (для «Not Found») или 200 (для «OK»)

statusText
текстовое сообщение статуса

Здесь все необходимые свойства и методы этого объекта, которые помогут нам решить наш таск. Опишем последовательность наших действий:

1. Создание экземпляра объекта XMLHttpRequest.
2. Объявление обработчика события onreadystatechange нашего экземпляра .
3. Открытие соединения с указанием типа запроса, URL и других параметров.
4. Посыл запроса.

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

Итак, пункт первый — создание экземпляра объекта. Вот здесь всплывает особенность обеспечения кроссбраузерности. Конструкция создания объекта различна: в IE 5+ она реализована через ActiveXObject, а в остальных браузерах (Mozilla, Netscape и Safari) — как встроенный объект типа XMLHttpRequest.

Для Internet Explorer:

Для всех остальных:

Таким образом, чтобы обеспечить кроссбраузерность, нужно лишь проверять наличие объектов window.XMLHttpRequest и window.ActiveXObject и применять соответствующий вызов создания экземпляра.

Далее по плану — создание обработчика событий и открытие соединения. Это весьма просто:

Ну и последний пункт — посыл запроса — метод send() (для версии без ActiveX в качестве параметра нужно передать null).

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

Исходя из всего вышесказанного, JavaScript код будет примерно следущим:

Теперь HTML-формы нашего примера:

Обратите внимение на фрагмент, выделенный зеленным цветом — событие onClick кнопки «Поиск». Мы вызываем функицю doLoad(…), в качестве параметра которой передаем адрес backend-скрипта, выполняющего поиск в базе зарегистрированного пользователя. О backend-скрипе чуть позже, имя его мы определили как ajaxsearch.php. Также GET-параметром скрипту мы передаем переменную search, со значением, взятым из поля ввода для ника.

И, как было сказано выше, объявим дополнительные HTML-элементы (в нашем случае — это невидимые слои) для отображения полученного содержимого и окна загрузки с возможностью отмены:

Ну что ж, с frontend’ом разобрались, переходим к backend’у — скрипт ajaxsearch.php. И вновь мы сталкиваемся с небольшими нюансами: для того, чтобы PHP-скрипт корректно работал с XMLHttpRequest, он (скрипт) должен посылать ряд заголовков. А именно: тип содержимого и его кодировку (особенно важно, если вы работаете с кириллицей), а также параметры кеширования — любое кеширование должно быть отключено (ну это и понятно — необходимо иметь свежую информацию).

Послать эти заголовки можно, примерно, так:

И еще одна особенность: если вы будете выводит данные в формате text/plane (в нашем случае — text/html, поэтому нас это не каснется, но все же — чтобы знать), помните, что спецсимволы такие как n, t, r и т.д., обрабатываются по умолчанию только в строках с двойными кавычками:

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

Ну вот, друзья, собственно, и все на сегодня.

Ajax-запрос

Материал из JQuery

url — адрес запроса.
settings — в этом параметре можно задать настройки для данного запроса. Задается с помощью объекта в формате . Ни одна из настроек не является обязательной. Установить настройки по умолчанию можно с помощью метода $.ajaxSetup().

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

Содержание

Список настроек

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

beforeSend относится к ajax-событиям. Поэтому если указанная в нем функция вернет false, ajax-запрос будет отменен.

Начиная с jQuery-1.5, beforeSend вызывается независимо от типа запроса.

Начиная с jQuery-1.5, в параметр complete можно передать не одну функцию, а массив функций. Все функции будут вызваны в той очередности, в которой заданы в этом массиве.

В качестве контекста можно задать DOM-элемент, который должен каким-либо образом сигнализировать о завершении запроса:

В случае запроса методом GET, строка с данными добавляется в конец url. Если данные задаются с помощью объекта, то он должен соответствовать формату: .

Событие error не определено для dataType равных script и JSONP.

Рекомендуется устанавливать значение параметраisLocal глобально — с помощью функциии $.ajaxSetup(), а не в настройках отдельных ajax-запросов.

Начиная с jQuery-1.5, указав в этом параметре false, вы предотвратите добавление в url дополнительного параметра. В этом случае необходимо явно установить значение свойства jsonpCallback. Например так: .

Начиная с jQuery-1.5, вы можете указать функцию в этом параметре, для того, чтобы обработать ответ сервера самостоятельно. В этом случае, указанная функция должна возвращать полученные от сервера данные (в указанной функции они будут доступны в первом параметре).

Функции, реагирующие на коды удачного выполнения запроса будут получать те же аргументы, что и функции-обработчики удачного выполнения запроса (указанные в параметре success), а функции, срабатывающие на коды ошибок, будут такими же, как и у error-функций.

Время отсчитывается с момента вызова функции $.ajax. Может случиться так, что в этот момент будет запущено несколько других запросов и браузер отложит выполнение текущего запроса. В этом случае timeout может завершиться, хотя фактически, запрос даже еще не был запущен.

В jQuery-1.4 и младше, при завершении времени ожидания, объект XMLHttpRequest перейдет в состояние ошибки и доступ к его полям может вызвать исключение. В Firefox 3.0+ запросы типа script и JSONP не будут прерваны при превышении времени ожидания. Они будут завершены даже после того как это время истечет.

В jQuery-1.5 свойство withCredentials не поддерживается нативным XMLHttpRequest и при кроссдоменном запросе это поле будет проигнорировано. Во всех следующих версиях библиотеки, это исправлено.

Обработчики событий

Настройки beforeSend, error, dataFilter, success и complete (их описание есть в предыдущем разделе) позволяют установить обработчики событий, которые происходят в определенные моменты выполнения каждого ajax-запроса.

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

Пример простого использования. Выведем сообщение при удачном выполнении запроса:

Начиная с jQuery-1.5, метод $.ajax() возвращает объект jqXHR, который помимо прочего реализует интерфейс deferred, что позволяет задавать дополнительные обработчики выполнения. Помимо стандартных для объекта deferred методов .done(), .fail() и .then(), с помощью которых можно устанавливать обработчики, в jqXHR реализованы .success(), .error() и .complete(). Это сделано для соответствия привычным названиям методов, с помощью которых устанавливаются обработчики выполнения ajax-запросов. Однако начиная с jQuery-1.8 эти три метода станут нежелательными для использования.


Для некоторых типов запросов, таких как jsonp или кроссдоменных GET-запросов, не предусматривается использование объектов XMLHttpRequest. В этом случае, передаваемые в обработчики XMLHttpRequest и textStatus будут содержать значение undefined.

Внутри обработчиков, переменная this будет содержать значение параметра context. В случае, если он не был задан, this будет содержать объект настроек.

Параметр dataType

Функция $.ajax() узнает о типе присланных сервером данных от самого сервера (средствами MIME). Кроме этого, существует возможность лично указать (уточнить), как следует интерпретировать эти данные. Это делается с помощью параметра dataType. Возможные значения этого параметра:

"xml" — полученный xml-документ будет доступен в текстовом виде. С ним можно работать стандартными средствами jQuery (также как и с документом html). "html" — полученный html будет доступен в текстовом виде. Если он содержит скрипты в тегах

AJAX Пример PHP

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

Пример Ajax PHP

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

Пример

Начните вводить имя в поле ввода ниже:

Пример объяснено

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

Функция запускается событием OnKeyUp.

Пример

Start typing a name in the input field below:

jQuery.ajax()

Выполняет асинхронный HTTP (Ajax) запрос

version added: 1.5 jQuery.ajax( url [, settings] )

url
Тип: Строка
URL адрес, на который будет отправлен Ajax запрос

settings
Тип: Объект
Набор параметров вида ключ / значение, которые настраивают запрос Ajax. Все настройки опциональны. По умолчанию настройки берутся из $.ajaxSetup(). Ниже приведен полный список всех настроек.

version added: 1.0 jQuery.ajax( settings )

settings
Тип: Объект
Набор параметров вида ключ / значение, которые настраивают запрос Ajax. Все настройки опциональны. По умолчанию настройки берутся из $.ajaxSetup().

settings:

Тип данных
accepts

По умолчанию: зависит от типа данных

При выполнении ajax-запроса, в заголовках (header) указываются допустимые типы содержимого, ожидаемого от сервера. Значения этих типов будут взяты из параметра accepts . Если требуется его изменить, лучше сделать это с помощью метода $.ajaxSetup().

async

По умолчанию: true

По умолчанию, все запросы отсылаются асинхронно (значение данного параметра true). Если же вам нужны синхронные запросы, то параметру async выставите значение false. Кроссдоменные запросы и dataType: "jsonp" не выполняются в синхронном режиме. Учтите, синхронные запросы могут на время выполнения запроса заблокировать браузер.

beforeSend(jqXHR jqXHR , объект settings)

Функция, которая будет вызвана непосредственно перед отправкой ajax-запроса на сервер. Она может быть использована для модификации jqXHR-объекта (в ранних версиях, до jQuery 1.4.x использовался XMLHttpRequest). Так же может использоваться для изменения заголовков (headers) и т.д. Объект типа jqXHR и объект настроек, передаются в качестве аргументов. Возврат значения false в функции beforeSend вызовет отмену ajax-запроса. Начиная с jQuery 1.5, beforeSend сработает вне зависимости от типа запроса.

cache

По умолчанию: true, false для типов данных 'script' and 'jsonp'

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

complete( jqXHR jqXHR, строка textStatus)

Функция, которая будет вызвана после завершения ajax запроса (срабатывает после функций-обработчиков success и error). Функция принимает два аргумента: объект типа jqXHR (в ранних версиях, до jQuery 1.4.x использовался XMLHttpRequest) и строку, характеризующую статус запроса ("success", "notmodified", "error", "timeout", "abort", или "parsererror"). Начиная с jQuery 1.5, complete может принимать массив функций.

contents

Параметр задается в формате <строка:регулярное выражение>и определяет, как jQuery будет разбирать ответ от сервера, в зависимости от его типа. (добалено в версии 1.5)

contentType

По умолчанию: 'application/x-www-form-urlencoded; charset=UTF-8'

При отправке Ajax запроса, данные передаются в том виде, в котором указаны в данном параметре. По умолчанию используется 'application/x-www-form-urlencoded; charset=UTF-8'. Если задать значение самим, то оно будет отправлено на сервер. Если кодировка не указана, то по умолчанию будет использоваться кодировка выставленная на сервере.

context

Объект, который станет контекстом после выполнения запроса (передаваемое значение в переменную this). Например, если указать в качестве контекста DOM-элемент, то все обработчики ajax-запроса тоже будут выполняться в контексте данного DOM-элемента. В данном примере ключевое слово this будет содержать document.body:

converters

Определяет, с помощью каких функций будет производиться конвертация значений из одного типа, в другой. (добалено в версии 1.5)

crossDomain

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

Если вы хотите, чтобы выполнить кросс-доменный запрос (например, JSONP) на том же домене, выставите true в настройке crossDomain. Это позволяет, например, сделать серверные перенаправление на другой домен. (добалено в версии 1.5)

Данные, которые будут переданы на сервер. Если данные не являются строкой, то они конвертируются в строку запроса. Для запросов типа GET данные прикрепляются к URL. Объект должен состоять из пар ключ/значение. Если в значении массив, то jQuery упорядочивает значения в зависимости от настройки traditional. По умолчанию, например, превращается в &foo=bar1&foo=bar2.

dataFilter( строка data, строка type)

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

dataType

По умолчанию: автоматически определяемая строка (xml, json, script, или html)

Тип данных, ожидаемых от сервера. Если опция не определена, то jQuery попытается определить тип, основываясь на MIME-типе ответа.

error( jqXHR jqXHR, строка textStatus, строка errorThrown)

Функция, исполняемая в случае неудачного запроса. Принимает 3 аргумента: объект jqXHR (в прошлом XMLHttpRequest), строку с описанием ошибки, а так же строку исключения, если оно было выбрашено. Второй аргумент может содержать следующие значения: null, "timeout", "error", "abort", и "parsererror". В случае если происходит HTTP ошибка, то в третий аргумент будет записан её текстовой статус. К примеру, "Not Found" или "Internal Server Error.". Начиная с jQuery 1.5, вместо одной функции, этот параметр может принимать массив функций. Событие error не происходит при dataType равному script или JSONP.

global

По умолчанию: true.

Вызывать или нет глобальные обработчики событий Ajax для этого запроса (например ajaxStart или ajaxStop).

headers

По умолчанию: <>

Здесь можно указать дополнительные заголовки запроса (header). Значения этой настройки будут введены до вызова функции beforeSend, в которой могут быть внесены окончательные изменения в заголовки. (добалено в версии 1.5)

ifModified

По умолчанию: false

Запрос будет считаться успешным только в случае, если данные ответа изменились со времени последнего запроса. Проверка осуществляется по заголовку Last-Modified. По умолчани, данная опция отключена. В jQuery 1.4 так же проверяется значение 'etag', для отслеживания факта изменения данных.

isLocal

По умолчанию: в зависимости от текущей локации

Параметр определяет, запущена ли веб-страница локально (например по протоколу file, *-extension, и w >(добалено в версии 1.5)

jsonp

Определяет имя параметра, который добавляется в url JSONP-запроса(по умолчанию, используется "callback"). К примеру настройка преобразуется в часть url строки 'onJSONPLoad=?'. Начиная с версии 1.5, указание в этом параметре false предотвращает добавление в url дополнительного параметра. В этом случае, необходимо установить значение настройки jsonpCallback. Например так: .

jsonpCallback

Функция, которая будет вызвана при ответе сервера на запрос типа JSONP. По умолчанию, jQuery генерирует произвольное уникальное имя этой функции, что более предпочтительно. Если вы хотите использовать кэширование GET запросов, то вписывайте название функции сами. Начиная с версии 1.5 можно указать функцию, для того, чтобы обработать ответ сервера самостоятельно.

mimeType

Здесь можно указать тип данных, в котором ожидается ответ от сервера вместо XHR. (добалено в версии 1.5.1)

password

Пароль, который будет использоваться в ответ на запрос проверки подлинности доступа HTTP (если это требуется)

username

Имя пользователя, которое будет использоваться в ответ на запрос проверки подлинности доступа HTTP (если это требуется)

processData

По умолчанию: true;

По умолчанию передаваемые на сервер данные преобразуются из объекта в строку запроса и отправляются как "application/x-www-form-urlencoded". Если вам необходимо отправить DOM-документ или иные данные, которые нельзя подвергать конвертированию установите опцию processData в false.

scriptCharset

Применяется только для Ajax GET-запросов типов 'JSONP' и 'script '. Если сервер на стороннем домене использует кодировку, отличную от вашей, необходимо указать кодировку стороннего сервера.

statusCode

Набор пар, в котором кодам выполнения запроса сопоставляются функции, которые при этом будет вызваны. Например, для кода 404 (страницы не существуют) можно сделать вывод сообщения на экран:

Если запрос прошёл успешно, то в качестве параметра, анонимная функция будет принимать те же параметры, что и при success. При ошибке, будет принимать то же самое что и при функции-обработчике error. (добалено в версии 1.5)

success( объект data, строка textStatus, объект jqXHR)

Функция, которая будет вызвана в случае успешного завершения запроса. Принимает 3 аргумента - данные (data), присланные сервером и прошедшие предварительную обработку; строка со статусом выполнения (textStatus); объект jqXHR (в версиях до 1.5 вместо jqXHR используетсяXMLHttpRequest). С версии jQuery 1.5, вместо одной функции, этот параметр может принимать массив функций.

timeout

Время ожидания ответа от сервера в миллисекундах. Переписывает глобальную настройку этого же параметра в $.ajaxSetup(). Если это время будет превышено, запрос будет завершен с ошибкой и произойдет событие error, которое будет иметь статус "timeout".

traditional

По умолчанию: false

Установите значение этого параметра в true, для того, чтобы использовать традиционный стиль сериализации.

По умолчанию: GET

Определяет тип запроса GET или POST. Можно также использовать другие HTTP-запросы (такие как PUT или DELETE), но следует помнить, что они поддерживаются не всеми бразерами.

По умолчанию: текущая страница.

Страница, накоторую будет отправлен запрос.

По умолчанию ActiveXObject в IE, XMLHttpRequest в других браузерах.

Callback-функция, для создания объекта XMLHttpRequest. Создав свою функцию, вы берёте на себя всю ответственность за формирование объекта.

xhrFields

Объект вида <имя:значене>для изменения значений соответствующих полей объекта XMLHttpRequest.

(добалено в версии 1.5.1)

Примеры

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

Получить последнюю версию HTML страницы

Передаём в качестве данных XML документ. Отключаем автоматическую конвертацию данных в обычную строку, задав настройке processData значение false :

Отправить на сервер значение ID. Сохранить данные, оповестить пользователя. Если запрос не прошёл, сообщить об этом пользователю.

Введение в AJAX

История и текущее состояние популярного подхода к разработке Web-приложений

За последние несколько лет язык JavaScript прошел путь от «вечно отстающего» и объекта насмешек до ключевого языка Web-программирования. Если попытаться выделить ключевой фактор, способствовавший росту популярности JavaScript, то это появление приложений на основе технологии AJAX.

Наработка навыков использования JavaScript

Эта статья является частью курса по развитию навыков использования JavaScript. Дополнительную информацию можно найти в полном руководстве по JavaScript.

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

Краткая история AJAX

История технологии AJAX, которая, казалось бы, мгновенно завоевала огромную популярность, похожа на историю других прорывных технологий. Хотя кажется, что эта технология появилась из ниоткуда, на самом деле для этого потребовалось определенное время. Несколько лет исследований в области Web-разработки привели к созданию инструментов и подходов, которые распространялись под «брендом» AJAX. Начиная с эры DHTML в период первоначального Интернет-бума и на протяжении "темных" лет после массового краха доткомов разработчики по всему миру открывали для себя неожиданные возможности JavaScript, открывающие новые пути для разработки Web-приложений.

XMLHttpRequest

Первый и самый важный компонент технологии AJAX – это XMLHttpRequest (XHR) API. XHR – это JavaScript API для передачи данных в виде сообщений между Web-браузером и Web-сервером. Этот API позволяет использовать HTTP POST -запросы (для передачи данных на сервер) и GET -запросы (для загрузки данных с сервера в фоновом режиме). XHR – это "ядро" большинства AJAX-вызовов и одна из важнейших технологий в современном Web-программировании.

Наконец, XHR - это лучший подарок Интернет-сообществу, сделанный командой Microsoft® Internet Explorer®.

Это действительно так. XHR впервые появился в пятой версии Internet Explorer в 2000 г. Изначально написанный Алексом Хопманном (Alex Hopmann) в виде элемента управления Microsoft® ActiveX®, XHR был создан для использования в Microsoft Outlook® Web Access и предназначался для "сглаживания" взаимодействия между передовым для того времени пользовательским интерфейсом и Microsoft Exchange Server.

Хотя пакет от Microsoft нельзя считать скромным началом, но XHR определенно переросл рамки исходного продукта. С тех времен XHR был интегрирован во все основные Web-браузеры и даже был признана W3C в качестве стандарта.

Первооткрыватели

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

Oddpost

Oddpost — это функционально насыщенный Web-клиент для электронной почты, выпущенный в 2002 году. В нем использовались многие подходы, сохранившие популярность и по сей день. По стилю и функциональности он напоминал стандартный клиент для работы с электронной почтой. Но в его реализации применялась технология DataPacks, позволяющая передавать небольшие фрагменты данных между сервером и Web-браузером. В то время такое решение считалось инновационным.

В дальнейшем Oddpost был куплен компанией Yahoo! и использовался в качестве основы при создании обновленной версии Yahoo! Mail.

Google Maps, Google Suggest, Gmail и одна важная статья

Видимые изменения начались несколько лет назад с появления Gmail, Google Suggest и Google Maps. Все эти проекты интенсивно использовали AJAX-подход и радикально изменили область разработки Web-приложений. Их отзывчивость и интерактивность поразили рядовых пользователей, и продукты Google быстро завоевали популярность у активной части Интернет-сообщества.

Хотя не все об этом знали, но область разработки Web-приложений ожидали еще более значительные изменения. Пользователи понимали, что Web-приложения меняются и приобретают новые замечательные возможности, но в чем конкретно заключаются эти изменения, было неизвестно.

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

18 февраля 2005 года Джесси Джеймс Гаррет (Jesse James Garrett), сооснователь и президент компании Adaptive Path, написал статью "Ajax: A New Approach to Web Applications" (см. ссылку в разделе Ресурсы). В этой статье он описал подход к разработке Web-приложений, который уже использовался в таких приложениях, как Gmail и GoogleMaps. Он назвал это "фундаментальным сдвигом в возможностях, доступных Web-приложениями".

Также он дал название данному подходу. Это важно, так как новый термин сфокусировал внимание сообщества на самом тренде и стал отправной точкой для обсуждения новых возможностей разработки Web-приложений. В статье Гаррета термин AJAX описывался следующими словами.

Определение AJAX
AJAX — это не технология. На самом деле AJAX — это новое объединение нескольких технологий, каждая из которых сильна в своей области. AJAX включает в себя:

  • стандартное представление с помощью XHTML и CSS;
  • динамическое отображение и интерактивность благодаря DOM;
  • обмен и манипулирование данными с помощью XML и XSLT;
  • асинхронное получение данных с помощью XMLHttpRequest;
  • использование JavaScript для интеграции вышеперечисленных технологий.

Хотя это техническое описание несколько устарело, основная идея сохранилась: HTML и CSS представляют данные и стиль; DOM и связанные с ней методы позволяют обновлять страницу в режиме реального времени, XHR отвечает за общение с сервером, а JavaScript управляет процессом в целом.

Общий эффект от этой статьи был ошеломительным. Она представляла собой редкий случай, когда рекламные обещания, объединившись с огромной креативной энергией, действительно привели к революции. Подхваченная новым поколением стартапов, которые начали появляться по всему миру, технология AJAX быстро оказалась на передовой линии Web-разработки. Эта технология прошла путь от тренда с неясной маркетинговой перспективой до ключевого компонента современных Web-дизайна и Web-разработки.

Библиотеки

Одним из ключевых факторов, способствовавших развитию Web-разработки на основе AJAX, стало появление и внедрение нескольких высокофункциональных JS-библиотек. За исключением опытных JS-разработчиков мало кто в действительности понимал, как работают технологии, формирующие AJAX. Поэтому, хотя многие аспекты интерактивности и анимации внутри Web-браузера в эпоху DHTML были доведены почти до предела возможного, сложность использования AJAX привела к большому разрыву между потребностями в Web-сайтах с AJAX-возможностями и количеством людей, способных создавать такие интерфейсы с нуля. Библиотеки, подобные Prototype, Dojo и jQuery, помогли преодолеть этот разрыв, предоставив готовую функциональность, которая позволила реализовать анимацию и интерактивность, преодолеть различия между Web-браузерами и сгладить недостатки базового JavaScript API.

Асинхронный JavaScript и не только

Одним из крупнейших изменений в мире AJAX с момента его зарождения и до сегодняшнего дня стало появление JSON - протокола для обмена данными на основе JavaScript. JSON, благодаря небольшому объему передаваемой информации и удобному доступу с помощью родного JavaScript API (в отличие от сложных методов и свойств, основанных на DOM и XML), был быстро принят разработчиками в качестве стандартного транспортного протокола. С момента своего появления JSON также успел попасть в последнюю 5-ую версию спецификации ECMAScript.

JSON+Padding

Стоит также упомянуть одно важное усовершенствование исходной спецификации JSON - JSON+Padding (JSONP). Как будет показано, объект XMLHttpRequest обладает строгой моделью безопасности, которая допускает взаимодействие только в рамках того же домена и протокола, которые использовались при запросе страницы. JSONP предоставляет элегантный способ обойти это ограничение, поместив JSON-отклик в callback-функцию или переменную, объявленную пользователем. После того, как JSON сценарий будет добавлен в документ, доступ к данным, лежащим в объекте, можно будет получить через этот метод. Сегодня этот подход стал фактически стандартом. Например, крупные Web-сервисы используют его для объединения и связывания информации из разных источников.

Но, несмотря на свою популярность, JSONP обладает очевидной уязвимостью, которой могут воспользоваться злоумышленники. Возможность «инъекции» тега script со стороны позволяет выполнить на базовой странице любое действие, что создает невероятные возможности для нанесения вреда пользователям, если источник данных был скомпрометирован или основной Web-сайт не интересуется происхождением ресурсов, добавляемых на его страницы.

Теперь, после изучения истории, можно переходить к изучению самой технологии. Так как базовый JavaScript API находится «в тени» библиотек, то даже для опытных разработчиков будет интересно узнать, как всё это работает на самом деле.


XMLHttpRequest API и его возможности

Хотя помимо XHR существуют и другие подходы для получения данных с сервера, именно XHR остается "ядром" большинства AJAX-приложений. Взаимодействие на основе XHR строится на двух компонентах: запрос и ответ. Ниже будут рассмотрены обе эти составляющие.

Модель безопасности

Как уже говорилось, исходный объект XMLHttpRequest обладает четкой моделью безопасности. Политика "same-origin" (объекты, происходящие из одного места) позволяет взаимодействовать только с тем хостом, протоколом и портом, которые использовались запрошенной страницей. Это означает, что общение между различными доменами (example.com и example2.com), различными хостами (my.example.com и www.example.com) и различными протоколами (http://example.com и https://example.com) запрещено и приводит к возникновению ошибки.

Однако благодаря разработке консорциумом W3C второй версии XHR-объекта и нового протокола Cross-origin Request Protocol и реализации этих концепций в большинстве Web-браузеров, включая InternetExplorer 8+, Mozilla Firefox 3.5+, Apple Safari 4+ и Google Chrome, появилась возможность выполнять запросы между доменами. Хотя для этого и потребовалось время, но теперь, указав в запросе специальный заголовок Origin :

и настроив сервер отправлять обратно соответствующий заголовок Access-Control-Allow-Origin :

стало возможным осуществлять дуплексное взаимодействие между доменами с помощью XHR-объектов.

Запрос (request)

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

  • open() – открывает подключение к серверу и принимает несколько аргументов:
    • method - используемый HTTP-метод (допускается POST или GET )
    • url - запрошенный URL-адрес.
    • async - необязательный Boolean -параметр, сигнализирующий о том является ли запрос асинхронным или нет (по умолчанию равен True ).
    • user – необязательный параметр, содержащий имя пользователя для аутентификации.
    • password – необязательный параметр, содержащий пароль, используемый для аутентификации.
  • setRequestHeader() – устанавливает заголовки запроса и принимает два аргумента: header (имя заголовка) и value (значение заголовка).
  • send() – отправляет запрос и может принимать необязательный параметр, содержащий тело POST -запроса.
  • abort() – прерывает отправку запроса.

Ответ (response)

Объект response также обладает определенными атрибутами и методами:

  • status – стандартный HTTP-статус запроса (например, в случае успешного выполнения запроса будет возвращено значение 200 ).
  • statusText – строка, содержащая полное описание статуса, возвращенного Web-сервером (например, 304 Not Modified ).
  • getResponseHeader() – возвращает значение определенного заголовка ответа; в качестве параметра принимает имя запрашиваемого заголовка.
  • getAllResponseHeaders() – возвращает текстовое содержание всех заголовков ответа.
  • responseText – атрибут, в котором хранится текстовое представление тела запроса.
  • responseXML – атрибут, содержащий XML-представление тела запроса – фрагмент документа с DOM и всеми соответствующими методами.

Состояние readyState

После создания объект XMLHttpRequest может находиться в одном из пяти состояний, перечисленных ниже:

  • 0: UNSENT – объект только что был создан.
  • 1: OPENED – был успешно вызван метод open() данного объекта.
  • 2: HEADERS_RECEIVED – заголовки ответа были успешно загружены.
  • 3: LOADING – тело ответа загружается.
  • 4: DONE – запрос был выполнен, но неизвестно – успешно или нет (информацию о результате выполнения запроса можно получить с помощью стандартных статусов и заголовков HTTP-ответа).

Пример, использующий базовый JavaScript API

Прежде чем переходить к рассмотрению популярных библиотек, стоит изучить несколько примеров на "чистом" JavaScript, чтобы разобраться, как работает базовая технология. Все представленные примеры можно найти в разделе "Материалы для скачивания" и запустить на любом Web-сервере с поддержкой PHP. Все примеры работают с документом, представленным в листинге 1.

Листинг 1. Пример HTML-документа

В листинге 2 представлен простой GET -запрос, обрабатывающий объект responseXML . Этот пример AJAX-вызова выполнен в духе первых лет этой технологии, но он работает во всех современных Web-браузерах, включая Internet Explorer версий 7 и 8.

Листинг 2. Базовая AJAX-функция

В листинге 3 используется оригинальный ActiveX объект. В случае, если его реализация отсутствует, с помощью блока try … catch выполняется поиск потенциальных ссылок на этот объект в других версиях Internet Explorer. Этот пример полностью совместим с различными версиями Web-браузера Internet-Explorer начиная с версии 5.

Листинг 3. AJAX-сценарий, совместимый с различными Web-браузерами семейства IE

В листинге 4 приведен подход, чаще всего используемый сегодня: получение объекта responseText в формате JSON и преобразование его в "родной" JS-объект. Как видно из примера, работать с JSON-данными очень просто. Если сравнить этот листинг с порой неочевидными и многословными методами обработки XML-данных, станет ясно, почему большинство разработчиков в качестве транспортного протокола выбрали именно JSON.

Листинг 4. Использование JSON

Во всех последующих листингах (с 5 по 11) используются JSON-данные.

В листинге 5 приведен простой пример JSONP. Как можно заменить, в нем полностью игнорируется XHR, а к сценарию просто добавляется callback-аргумент. Когда callback-вызов срабатывает (сервер возвращает ответ), полученный объект с данными помещается в исполняемый JS-код.

Листинг 5. Пример использования JSONP

Использование AJAX-библиотек

Для большинства программистов внутренняя структура AJAX-запроса интересна только с академической точки зрения, так как основная часть их работы выполняется в контексте одной или нескольких JS-библиотек. Кроме решения проблем совместимости между различными Web-браузерами, библиотеки также предоставляют функциональность, надстроенную над базовым API. В следующих примерах показывается, как выполнять GET - и POST - запросы с помощью API трех наиболее популярных библиотек.

jQuery

Сначала рассмотрим пример, использующий популярную библиотеку jQuery. Поддержка AJAX в jQuery была не так давно переписана, чтобы добавить новую функциональность, описание которой выходит за рамки данной статьи. Однако общей чертой всех AJAX-запросов в jQuery является наличие объекта с конфигурацией, передаваемого функции в качестве аргумента. Стоит отметить, что в jQuery есть несколько удобных методов, таких как $.post и $.get, служащих для быстрого доступа к конфигурации стандартных запросов.

В листинге 6 приведен исходный код, выполняющий загрузку данных с помощью jQuery.

Листинг 6. Реализация GET-запроса в jQuery

В листинге 7 показано, как использовать POST -запрос для получения JSON-объекта. В данном случае для "разбора" полученных данных используется "родной" объект JSON. В документации jQuery говорится о том, что неподдерживающие Web-браузеры необходимо дополнить сценарием JSON2.js.

Добавление специального обработчика для ошибок позволяет обрабатывать как удачные, так и неудачные запросы. В jQuery для описания ошибки используются три аргумента, включая сам XHR-объект, что позволяет наладить надежную обработку ошибок.

Листинг 7. Реализация POST-запроса в jQuery

Как будет видно из следующих примеров, библиотека Dojo способна на большее, нежели простое манипулирование DOM-объектом и отправка AJAX-запросов. Её возможности позволяют создавать самые сложные приложения, но все равно стоит изучить её API и с такой "начальной" позиции.

В Dojo есть две специальные AJAX-функции: xhrGet и xhrPost . Кроме того, для разбора полученных данных используется JSON-утилита, входящая в Dojo. В листинге 8 приведен пример создания GET -запроса.

Листинг 8. Реализация GET-запроса в Dojo

В листинге 9 приведен пример обработки POST -запроса с конфигурацией обработчика ошибок.

Листинг 9. Реализация POST-запроса в Dojo

Yahoo! User Interface (YUI)

В библиотеке YUI используется немного другой подход, отличающийся от рассмотренных ранее. При использовании YUI всегда возвращается XHR-объект полностью, а не только "разобранные данные", что обеспечивает лучший доступ к данным, хранящимся в запросе, и позволяет более гибко манипулировать ими. Также это значит, что программист должен знать особенности внутренней реализации XHR-объекта. В виде отступления от основной темы в примерах показывается, как использовать загрузочный модуль YUI.use() , который хотя и не относится непосредственно к AJAX (за исключением загрузки модуля io ), но заслуживает отдельного упоминания. В листинге 10 этот модуль в качестве аргументов принимает список из других YUI-модулей и callback-функцию. После запуска он создает пакет, в котором все необходимые модули содержатся в одном CDN-артефакте, загружаемом с Web-портала Yahoo! Content Delivery Network.

Листинг 10. Реализация GET-запроса в YUI

В листинге 11 приведен пример реализации POST -запроса, в котором используется интересный приём: выделение функций для обработки запроса в отдельный объект on .

Листинг 11. Реализация POST-запроса в YUI

Как можно видеть, базовые принципы, применяемые во всех листингах, в целом совпадают. За исключением поддержки ActiveX-компонентов и JSONP, все примеры охватывают одну и ту же область, отличаясь реализацией конкретных API, основанных на базовых возможностях JavaScript для создания интерактивных приложений.

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

Заключение

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

Ресурсы для скачивания

  • этот контент в PDF
  • примеры кода для этой статьи (sample-ajax-code.zip | 18KB)

Похожие темы

  • An introduction to Ajax: оригинал статьи (EN).
  • The Story of XMLHttp (Alex Hopmann) (EN): статья об истории XMLHttp.
  • Ajax: A New Approach to Web Applications (Jesse James Garret) (EN): статья-манифест, в которой впервые был подробно описан AJAX-подход.
  • JSON.org: Web-сайт, посвященный JSON.
  • ECMA-262 ECMAScript Language Specification 5th edition (декабрь 2009) (EN): информация о стандартизированной версии JSON.
  • Спецификация XMLHttpRequest 2 (EN).
  • Cross-origin Resource Sharing: публикация W3C, посвященная обмену информацией между различными доменами.
  • Исследование Николаса Закаса (Nicholas Zakas), посвященное организации AJAX-взаимодействия между различными доменами..
  • Ajax with Dojo: дополнительная информация о Dojo.
  • YUI3: IO: дополнительная информация о YUI3.
  • Присоединяйтесь к автору статьи в Твиттере.
  • Следите за публикациями developerWorks в Твиттере или подпишитесь на канал твитов по Linux на developerWorks.
  • Загрузить JSONP.
  • Дополнительная информация о методе jQuery.ajax() , входящем в jQuery API.
  • Дополнительная информация о JavaScript-библиотеке jQuery.
  • Загрузить Dojo Toolkit.
  • Загрузить библиотеку YUI.

Комментарии

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

AJAX на практике.

Запрос на чистом JavaScript.

Серия статей "Ajax на практике"

  • Основы передачи данных
  • Получение данных из формы
  • Загрузка файлов
  • Progress Bar - индикатор процесса загрузки
  • Запрос на чистом JavaScript.

Во всех четырёх статьях серии "Ajax на практике", мы разбирались, как использовать эту технологию с помощью библиотеки jQuery и, в частности, её метод $.ajax(), но всегда ли нужно прибегать к помощи фреймворков? К примеру, если в своём проекте, вы больше нигде не используете библиотеку, то абсолютно не резонно нагружать страницы лишними килобайтами и особенно, если этих килобайт около девяноста. Вывод - пишем ajax-запрос на чистом JavaScript, тем более, что та же библиотека jQuery, ни что иное, как подготовленный набор методов (функций), написанный на нативном JS. Если взять для сравнения JS-код из статьи "Получение данных из формы", то переписывая код, нам нужно будет сделать следующее:

  1. Дождаться загрузки всего документа
  2. Получить в распоряжение элемент
  3. Повесить на него обработчик события submit
  4. Подготовить данные формы на отправку
  5. Создать объект XMLHttpRequest
  6. С помощью XHR отправить данные
  7. Получить, обработать и вывести на экран ответ сервера

Поехали пошагово.
1) Вместо привычных $(function()<>) или $(document).ready(function()<>), устанавливаем свой обработчик события onload. Но прежде, хочу пояснить, почему мы не будем использовать конструкцию element.onevent = func;. Это способ хоть и кроссбраузерный, но главным его недостатком является то, что установив на один элемент два и более обработчика, последний "затрёт" предыдущие и они "не откатают свою обязательную программу". Поэтому, хоть кода на пару строк получится больше, но запишем так:

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

JavaScript Ajax

In this tutorial you will learn what Ajax is and how to implement it in JavaScript.

What is Ajax?

Ajax stands for Asynchronous Javascript And Xml. Ajax is just a means of loading data from the server and selectively updating parts of a web page without reloading the whole page.

Basically, what Ajax does is make use of the browser's built-in XMLHttpRequest (XHR) object to send and receive information to and from a web server asynchronously, in the background, without blocking the page or interfering with the user's experience.

Ajax has become so popular that you hardly find an application that doesn't use Ajax to some extent. The example of some large-scale Ajax-driven online applications are: Gmail, Google Maps, Google Docs, YouTube, Facebook, Flickr, and so many other applications.

Note: Ajax is not a new technology, in fact, Ajax is not even really a technology at all. Ajax is just a term to describe the process of exchanging data from a web server asynchronously through JavaScript, without refreshing the page.

Tip: Don't get confused by the term X (i.e. XML) in AJAX. It is only there for historical reasons. Other data exchange format such as JSON, HTML, or plain text can be used instead of XML.

Understanding How Ajax Works

To perform Ajax communication JavaScript uses a special object built into the browser—an XMLHttpRequest (XHR) object—to make HTTP requests to the server and receive data in response.

All modern browsers (Chrome, Firefox, IE7+, Safari, Opera) support the XMLHttpRequest object.

The following illustrations demonstrate how Ajax communication works:

Since Ajax requests are usually asynchronous, execution of the script continues as soon as the Ajax request is sent, i.e. the browser will not halt the script execution until the server response comes back.

In the following section we'll discuss each step involved in this process one by one:

Sending Request and Retrieving the Response

Before you perform Ajax communication between client and server, the first thing you must do is to instantiate an XMLHttpRequest object, as shown below:

Now, the next step in sending the request to the server is to instantiating the newly-created request object using the open() method of the XMLHttpRequest object.

The open() method typically accepts two parameters— the HTTP request method to use, such as "GET", "POST", etc., and the URL to send the request to, like this:

Tip: The file can be of any kind, like .txt or .xml , or server-side scripting files, like .php or .asp , which can perform some actions on the server (e.g. inserting or reading data from database) before sending the response back to the client.

And finally send the request to the server using the send() method of the XMLHttpRequest object.

Note: The send() method accepts an optional body parameter which allow us to specify the request's body. This is primarily used for HTTP POST requests, since the HTTP GET request doesn't have a request body, just request headers.

The GET method is generally used to send small amount of data to the server. Whereas, the POST method is used to send large amount of data, such as form data.

In GET method, the data is sent as URL parameters. But, in POST method, the data is sent to the server as a part of the HTTP request body. Data sent through POST method will not visible in the URL.

See the chapter on HTTP GET vs. POST for a detailed comparison of these two methods.

In the following section we'll take a closer look at how Ajax requests actually works.

Performing an Ajax GET Request

The GET request is typically used to get or retrieve some kind of information from the server that doesn't require any manipulation or change in database, for example, fetching search results based on a term, fetching user details based on their id or name, and so on.

The following example will show you how to make an Ajax GET request in JavaScript.

Example

When the request is asynchronous, the send() method returns immediately after sending the request. Therefore you must check where the response currently stands in its lifecycle before processing it using the readyState property of the XMLHttpRequest object.

The readyState is an integer that specifies the status of an HTTP request. Also, the function assigned to the onreadystatechange event handler called every time the readyState property changes. The possible values of the readyState property are summarized below.

логический
логический
функция или массив
логический
объект или строка
функция или массив
логический
логический
логический
строка или функция
логический
функция или массив
логический
Value State Description
UNSENT An XMLHttpRequest object has been created, but the open() method hasn't been called yet (i.e. request not initialized).
1 OPENED The open() method has been called (i.e. server connection established).
2 HEADERS_RECEIVED The send() method has been called (i.e. server has received the request).
3 LOADING The server is processing the request.
4 DONE The request has been processed and the response is ready.

Note: Theoretically, the readystatechange event should be triggered every time the readyState property changes. But, most browsers do not fire this event when readyState changes to 0 or 1. However, all browsers fire this event when readyState changes to 4 .

The status property returns the numerical HTTP status code of the XMLHttpRequest's response. Some of the common HTTP status codes are listed below:

  • 200 — OK. The server successfully processed the request.
  • 404 — Not Found. The server can't find the requested page.
  • 503 — Service Unavailable. The server is temporarily unavailable.

Please check out the HTTP status codes reference for a complete list of response codes.

Here's the code from our "greet.php" file that simply creates the full name of a person by joining their first name and last name and outputs a greeting message.

Example

Performing an Ajax POST Request

The POST method is mainly used to submit a form data to the web server.

The following example will show you how to submit form data to the server using Ajax.

Example

If you are not using the FormData object to send form data, for example, if you're sending the form data to the server in the query string format, i.e. request.send(key1=value1&key2=value2) then you need to explicitly set the request header using setRequestHeader() method, like this:

The setRequestHeader() method, must be called after calling open() , but before calling send() .

Some common request headers are: application/x-www-form-urlencoded , multipart/form-data , application/json , application/xml , text/plain , text/html , and so on.

Note: The FormData object provides an easy way to construct a set of key/value pairs representing form fields and their values which can be sent using XMLHttpRequest.send() method. The transmitted data is in the same format that the form's submit() method would use to send the data if the form's encoding type were set to multipart/form-data .

Here's the code of our "confirmation.php" file that simply outputs the values submitted by the user.

Example

For security reasons, browsers do not allow you to make cross-domain Ajax requests. This means you can only make Ajax requests to URLs from the same domain as the original page, for example, if your application is running on the domain "mysite.com", you cannot make Ajax request to "othersite.com" or any other domain. This is commonly known as same origin policy.

However, you can load images, style sheets, JS files, and other resources from any domain.

Tip: Check out the jQuery Ajax methods for quick and seamless Ajax implementation. The jQuery framework provides very convenient methods to implement Ajax functionality.

Парсинг JavaScript и AJAX на PHP

Парсинг сайтов

Сейчас мы с вами займемся парсингом сайтов, которые подгружают свой контент через AJAX или генерируют его на JavaScript.

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

Однако, свои нюансы есть и тут. Давайте с ними разбираться.

Парсинг AJAX

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

Как происходит обновление - страница шлет запрос на определенный URL, по обращению на который можно получить кусочек страницы. Если знать этот URL, то можно курлом отправить на него запрос и получить этот кусочек страницы, так же, как это делает браузер.

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

Тут скоро будет видео.

Возможные проблемы

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

Это отслеживание заключается в проверке сервером заголовка Referer со значением URL страницы, с которой должен был прийти аякс запрос и/или проверки наличия заголовка X-Requested-With со значением XMLHttpRequest.

Итак, если по вашему обращению на URL для аякса не появляется нужно вам содержимое - попробуйте отправить эти заголовки и страница магическим начнет работать:)

Парсинг JSON

Достаточно часто URL для аякса отдает не готовый HTML код, а данные в формате JSON. Это нам на руку - ведь их не нужно парсить, достаточно преобразовать их из джейсона в PHP массив. Это делает функция json_decode(строка в json, true) - первым параметром она принимает строку в формате JSON, а возвращает массив PHP, в который разобран этот JSON.

Нюанс: без второго параметра или когда он установлен в false функция json_decode возвращает объект. Работа с этим объектом похожа на работу с объектами phpQuery. В общем-то, как по мне - удобнее работать с массивом, поэтому проще передать второй параметр в значении true.

Парсинг JavaScript

Иногда бывает так, что данные не откуда не грузятся, а уже есть на странице, просто хранятся в массиве JavaScript. Признак: если страница меняется как будто работает AJAX, однако в отладчике никаких аякс запросов нет.

Что вам делать дальше:

Приступайте к решению задач по следующей ссылке: задачи к уроку.

Когда все решите - переходите к изучению новой темы.

AJAX Пример PHP

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

Пример Ajax PHP

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

Пример

Начните вводить имя в поле ввода ниже:

Пример объяснено

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

Функция запускается событием OnKeyUp.

Пример

Start typing a name in the input field below:

Топ-пост этого месяца:  Как определить, что это последняя страница пагинации
Добавить комментарий