Сайт о телевидении

Сайт о телевидении

» » Использование Ajax. Основы AJAX для начинающих

Использование Ajax. Основы AJAX для начинающих

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

Надеюсь, она будет полезна для понимания, что такое AJAX и с чем его едят.

Что такое AJAX ? Пример реализации.

AJAX, или, более длинно, A synchronous J avascript A nd X ml - технология для взаимодействия с сервером без перезагрузки страниц.

За счет этого уменьшается время отклика и веб-приложение по интерактивности больше напоминает десктоп.

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

Вот код кнопки в примере выше:

При нажатии она вызывает функцию vote , которая отправляет запрос на сервер, ждет ответа, а затем показывает сообщение об этом в div "е под кнопкой:

Здесь будет ответ сервера

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

Function getXmlHttp(){ var xmlhttp; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest!="undefined") { xmlhttp = new XMLHttpRequest(); } return xmlhttp; }

Более подробно о деталях реализации AJAX с использованием XmlHttpRequest и других транспортов можно почитать в разделе про общение с сервером .

Здесь мы не будем на этом останавливаться и перейдем сразу к функции vote:

// javascript-код голосования из примера function vote() { // (1) создать объект для запроса к серверу var req = getXmlHttp() // (2) // span рядом с кнопкой // в нем будем отображать ход выполнения var statusElem = document.getElementById("vote_status") req.onreadystatechange = function() { // onreadystatechange активируется при получении ответа сервера if (req.readyState == 4) { // если запрос закончил выполняться statusElem.innerHTML = req.statusText // показать статус (Not Found, ОК..) if(req.status == 200) { // если статус 200 (ОК) - выдать ответ пользователю alert("Ответ сервера: "+req.responseText); } // тут можно добавить else с обработкой ошибок запроса } } // (3) задать адрес подключения req.open("GET", "/ajax_intro/vote.php", true); // объект запроса подготовлен: указан адрес и создана функция onreadystatechange // для обработки ответа сервера // (4) req.send(null); // отослать запрос // (5) statusElem.innerHTML = "Ожидаю ответа сервера..." }

Поток выполнения, использованный vote, довольно типичен и выглядит так:

  • Функция создает объект XmlHttpRequest
  • назначает обработчик ответа сервера onreadystatechange
  • открывает соединение open
  • отправляет запрос вызовом send (ответ сервера принимается срабатывающей в асинхронном режиме функцией onreadystatechange)
  • показывает посетителю индикатор состояния процесса
  • Серверный обработчик, к которому обращен AJAX-запрос (в примере это vote.php) по сути ничем не отличается от обычной страницы. AJAX-запрос, отправляемый XmlHttpRequest , ничем не отличается от обычного запроса.

    Просто текст, который возвращает сервер, не показывается как HTML, а читается и обрабатывается функцией onreadystatechange .

    Смысл AJAX - в интеграции технологий

    Технология AJAX использует комбинацию:

    • (X)HTML, CSS для подачи и стилизации информации
    • DOM-модель, операции над которой производятся javascript на стороне клиента, чтобы обеспечить динамическое отображение и взаимодействие с информацией
    • XMLHttpRequest для асинхронного обмена данными с веб-сервером. В некоторых AJAX-фреймворках и в некоторых ситуациях, вместо XMLHttpRequest используется IFrame, SCRIPT-тег или другой аналогичный транспорт.
    • JSON часто используется для обмена данными, однако любой формат подойдет, включая форматированный HTML, текст, XML и даже какой-нибудь EBML

    Типичное AJAX-приложение состоит как минимум из двух частей.

    Первая выполняется в браузере и написана, как правило, на JavaScript, а вторая - находится на сервере и написана, например, на Ruby, Java или PHP .

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

    Что я могу сделать с помощью AJAX ?

    Смысл AJAX - в интерактивности и быстром времени отклика.

    Небольшие элементы управления

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

    Динамическая подгрузка данных с сервера.

    Например, дерево, узлы которого подгружаются по мере раскрытия.

    На момент его появления он явился единственным открытым почтовым сервисом, использующим AJAX для следующих фич.

    • Проверка ошибок ввода формы ДО сабмита

      На сервер передается имя пользователя, результат проверки возвращается на страницу.

    • "Мгновенная" загрузка

      Браузер обращается к серверу только за данными, а не обновляет весь громоздкий интерфейс

    • Автоматическая "доставка" писем в открытую папку

      Время от времени отправляется запрос на сервер и, если пришли новые письма, они появляются в браузере.

    • Автодополнение

      Достаточно ввести первые буквы имени адресата, и остальные дополняются автоматически, как в десктоп-приложениях.

    Результат: обширная популярность, высокий спрос на account"ы с момента открытия.

    Синхронная модель VS Асинхронная модель

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

    Условно говоря, мы действуем так:

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

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

    В асинхронном варианте - мы сначала задали программу, что делать при клеве, а затем опустили удочку ловить и занялись другими делами.
    Например, поставили еще 5 таких удочек.

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

    Существуют приемы, облегчающие асинхронное программирование, например, отложенный объект Deferred (Twisted,Dojo,Mochikit), но об этом - в отдельной статье.

    Синхронная и асинхронная модель в AJAX

    Вернемся к нашим баранам: браузеру, серверу и, скажем, базе данных.

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

    Все процессы выполняются последовательно, один за другим.

    Сетевые задержки включены во время ожидания, обозначенное на схеме серым цветом.

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

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

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

    Пользователь может написать комментарии, заполнить и отослать форму и т.п: Могут производиться новые асинхронные запросы.

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

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

    Особенно в случае нескольких одновременных асинхронных запросов, нужно заботиться об очередности выполнения и ответа (race-conditions) и, в случае ошибки, оставлять приложение в целостном (consistent) состоянии.

    Особенности асинхронной модели
    • Сложность в реализации
      • Недостаточные возможности браузера (javascript)
      • Асинхронная модель сложнее для отладки
    • Race conditions
      • Неопределена последовательность выполнения
      • Можно делать много одновременных задач ("удочек"), но задача, начатая первой, может окончиться последней.
    • Реакция тут же, но неизвестно, какой будет результат. Усложнена обработка ошибок
      • Ошибок коммуникации - разрыв связи, и т.п.
      • Пользовательских ошибок - например, не хватило привилегий
    • Контроль целостности (bugproof)
      • Например, редактор отправил асинхронный запрос на удаление ветки дерева. Добавление в нее нужно отключить, пока не придет ответ сервера. Если вдруг не хватило привилегий, то операция не удалась.
    • Интерактивность
    • Быстрый интерфейс

    Плюсов всего два, зато какие! Овчинка стоит выделки.

    Асинхронный drag"n"drop.

    Иногда для асинхронных операций необходимо делать различные "финты ушами". Например, хочется сделать drag"n"drop в дереве, т.е перетаскивать статьи из одного раздела в другой мышкой, и чтобы они на сервере в базе данных меняли родителя.

    Drag"n"drop - это "взял мышей объект - положил куда надо - готово". Но в асинхронной модели не может быть все прям сразу "готово".
    Надо проверить привилегии на сервере, проверить, существует ли еще объект, вдруг его удалил другой пользователь.

    Надо как-то показать, что процесс пошел, но результат "ща будет..". А как? В асинхронной модели указатель мыши не может просто так зависнуть над объектом, превратившись в часики.

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

    Stale context, устаревший контекст

    В примере с drag"n"drop также затронута проблема "stale context" - устаревшего контекста.

    Веб - многопользовательская среда. Если для навигации используется,
    скажем, дерево статей, то над ним работают много человек. Один из них может удалить ветку дерева, над которой работает другой: конфликт.

    Как правило, для преодоления таких казусов используются следующие средства:

    Политика редактирования

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

    Локинг и/или версионный контроль

    Локинг - блокирование редактируемых документов.

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

    Более подробно о локинге и версионности можно почитать, например, в документации к системе версионного контроля Subversion .

    Автообновление контекста

    Проблема устаревшего контента может быть на 99% решена при помощи мгновенного автообновления.

    Браузер держит постоянное соединение с сервером (или делает время от времени корректирующие запросы) - и нужные изменения отсылаются по этому каналу.

    Например, в раскрытую ветку дерева иногда подгружаются новые статьи, в открытый почтовый интерфейс - новые письма.

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

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

    Технология AJAX базируется на использовании объекта XMLHttpRequest(), который позволяет отправлять и получать информацию в различных форматах включая XML и HTML. Реализация технологии состоит из клиентской и серверной частей. Клиентская часть выполняется в браузере пользователя и пишется на JavaScript, а серверная выполняется на веб-сервере и пишется на любом языке веб-программирования: php, asp, perl и др.

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

    1. Создание объекта запроса XMLHttpRequest .
    В Internet Explorer и других браузерах создание объекта XMLHttpRequest отличается. Во всех браузерах кроме Internet Explorer этот объект создается очень просто: xmlHttp = new XMLHttpRequest(); Браузер Internet Explorer для создания объекта запроса использует анализатор MSXML. Кроме того существует две разных версии MSXML. Универсальный метод создания объекта запроса XMLHttpRequest для всех браузеров выглядит следующим образом:


    var xmlHttp=null;
    try
    {


    }
    catch (e)
    {

    try
    {
    xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e)
    {
    xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    }

    Создание объекта запроса происходит в строках xmlHttp = new XMLHttpRequest(); , xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); и xmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); . Остальные строки обрабатывают ошибки.

    2. Выполнение запроса .
    Для выполнения запроса необходимо открыть соединение с сервером, установить функцию, которая выполниться после ответа сервера и передать запрос.

    Чтобы указать функцию которая будет обрабатывать ответ, необходимо свойству onreadystatechange присвоить имя JavaScript функции: xmlHttp.onreadystatechange = MyFunc; . Причем имя функции указывается без скобок.

    Чтобы открыть соединение с сервером необходимо вызвать функцию open() . Эта функция имеет три обязательных параметра:

    • метод запроса HTTP - обычно используют "GET" или "POST" , но можно использовать любой другой метод в соответствии с HTTP стандартами ;
    • url запроса - адрес скрипта на сервере, который обрабатывает запрос;
    • асинхронность запроса - TRUE или FALSE, если TRUE, то запрос асинхронный и пользователь сможет продолжать работу со страницей.

    Для отправки запроса необходимо вызвать метод send() , параметром которого могут быть любые данные, которые вы хотите отправить на сервер. Данные должны быть сформированы в строку запроса param1=1¶m2=2¶m3=3 .

    Если данные отправляются методом POST, то необходимо изменить MIME-тип запроса: xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); .

    Выполнение запроса с использованием метода GET :

    /*Устанавливаем соединение*/
    xmlHttp.open("GET", "example.php?param1=1¶m2=2", true);
    /*Указываем функцию*/

    /*Отправляем запрос*/
    xmlHttp.send(null);

    И с использование метода POST :

    /*Устанавливаем соединение*/
    xmlHttp.open("POST", "example.php", true);
    /*Меняем MIME-тип*/
    xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    /*Указываем функцию*/
    xmlHttp.onreadystatechange = MyFunc;
    /*Отправляем запрос*/
    xmlHttp.send("param1=1¶m2=2");

    3. Обработка ответа сервера .
    Отправляя запрос, мы указали имя функции, обрабатывающей ответ сервера: xmlHttp.onreadystatechange = MyFunc; . Для начала, эта функция должна проверять статус запроса. Это можно сделать с помощью свойства readyState . Если xmlHttp.readyState = 4 , то ответ от сервера получен и можно приступать к его обработке. Далее необходимо проверить статус HTTP-ответа с помощью свойства status . Если xmlHttp.status = 200 значит все в порядке и можно продолжить обработку данных. Получить доступ к данным можно с помощью свойств responseText - в виде текста, либо responseXML - в виде объекта XMLDocument.

    Полный пример работы Ajax-приложения:


    /*переменная для хранения объекта запроса*/
    var xmlHttp=null;
    /*создание объекта запроса*/
    function createRequest()
    {
    try{
    //создаем объект запроса для Firefox, Opera, Safari
    xmlHttp = new XMLHttpRequest();
    } catch(e){
    //создаем объект запроса для Internet Explorer
    try{
    xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e){
    try{
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch(e){
    xmlHttp = null;
    }
    }
    }

    If(xmlHttp == null)alert("Браузер не поддерживает AJAX!");
    }

    /*отправка запроса*/
    function sendRequest()
    {
    /*получаем объект запроса*/
    createRequest();
    /*Устанавливаем соединение*/
    xmlHttp.open("GET", "ajax.php?param1=1¶m2=2", true);
    /*Указываем функцию*/
    xmlHttp.onreadystatechange = MyFunc;
    /*Отправляем запрос*/
    xmlHttp.send(null);
    }

    /*обрабатываем ответ*/
    function MyFunc()
    {
    if(xmlHttp.readyState == 4) {
    if (xmlHttp.status == 200) {
    alert(xmlHttp.responseText);
    } else {
    alert("Ошибка обработки запроса!");
    }
    }
    }

    Серверная часть может быть написана на чем угодно. Возвращаемое значение xmlHttp.responseText формируется стандартным выводом. Пример серверной части на php:

    Попробуйте пример в действии:

    И в дополнение некоторые справочные материалы по объекту XMLHttpRequest :
    Методы класса XMLHttpRequest


    Свойства класса XMLHttpRequest

    AJAX: С чего начать

    В этой статье рассмотрены основные принципы работы AJAX и даны два простых примера, использующих эту технологию.

    1 Что такое AJAX?
    2 Шаг 1 - Как послать HTTP запрос
    3 Шаг 2 - Обрабатываем HTTP ответ
    4 Шаг 3 - Простой пример
    5 Шаг 4 - Работа с XML ответом

    Что такое AJAX?

    Ajax означает Асинхронный JavaScript и XML. В основе технологии лежит использование нестандартного объекта XMLHttpRequest(), необходимого для взаимодействия со скриптами на стороне сервера. Объект может как отправлять, так и получать информацию в различных форматах включая XML, HTML и даже текстовые файлы. Самое привлекательное в Ajax - это его асинхронный принцип работы. С помощью этой технологии можно осуществлять взаимодействие с сервером без необходимости перезагрузки страницы. Это позволяет обновлять содержимое страницы частично, в зависимости от действий пользователя.

    Две особенности, которые мы рассмотрим:

    * Отправление запросов серверу без перезагрузки страницы
    * Работа с XML документами

    Шаг 1 - Как послать HTTP запрос

    Для того, чтобы послать HTTP запрос на сервер используя JavaScript, вам необходим экземпляр класса, который позволит это сделать. Такой класс впервые был введен в Internet Explorer как объект ActiveX, называемый XMLHTTP. Позже в Mozilla, Safari и другие броузеры был введен класс XMLHttpRequest, который поддерживал методы и свойства изначального объекта ActiveX от Microsoft.

    В результате, чтобы создать кросс-броузерный объект требуемого класса, вы можете сделать следующее:

    if (window.XMLHttpRequest) { // Mozilla, Safari, ...



    }

    (В целях наглядности код выше является немного упрощенным. Более жизненный пример будет рассмотрен в шаге 3 этой статьи)

    Некоторые версии некоторых броузеров Mozilla не будут корректно работать, если ответ сервера не содержит заголовка XML mime-type. Чтобы решить эту проблему вы можете использовать вызовы дополнительных методов для переопределения заголовка полученного от сервера, если он отличен от text/xml.

    http_request = new XMLHttpRequest();

    Далее вам необходимо решить, что вы будете делать после получения ответа сервера. На этом этапе вам необходимо указать объекту, какая JavaScript функция будет обрабатывать ответ. Это делается путем присваивания свойству onreadystatechange имени JavaScript функции, которую вы собираетесь использовать:

    Заметьте, что после названия функции нет скобок и не указано параметров, потому что вы просто присваиваете ссылку на функцию, а не вызываете ее. К тому же, вместо указания имени функции, вы можете использовать возможность JavaScript объявлять функции на лету (так называемые «анонимные функции») и указывать действия, которые тотчас же будут обрабатывать ответ:

    http_request.onreadystatechange = function(){
    // какой-нибудь код
    };

    http_request.open("GET", "http://www.example.org/some.file", true);
    http_request.send(null);

    * Первый параметр вызова функции open() - метод запроса HTTP (GET, POST, HEAD или любой другой метод, который вы хотите использовать). Используйте методы в соответствии с HTTP стандартами; иначе некоторые броузеры (такие как Firefox) могут не обработать запрос. Информация о допустимых HTTP запросах доступна по адресу спецификации W3C
    * Второй параметр - URL запрашиваемой страницы. Из соображений безопасности вы не можете запрашивать страницы сторонних доменов. Убедитесь, что вы используете одинаковое доменное имя на всех страницах, иначе вы получите ошибку "доступ запрещен" при вызове функции open(). Типичной ошибкой при доступе к сайту через site.ru является подача запросов на www.site.ru.
    * Третий параметр указывает, является ли запрос асинхронным. Если он TRUE, то выполнение JavaScript продолжится во время ожидания ответа сервера. В этом и заключается асинхронность технологии.

    Параметром метода send() могут быть любые данные, которые вы хотите послать на сервер. Данные должны быть сформированы в строку запроса:

    name=value&anothername=othervalue&so=on

    Заметьте, что если вы хотите отправить данные методом POST, вы должны изменить MIME-тип запроса с помощью следующей строки:

    http_request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    Иначе сервер проигнорирует данные отправленные методом POST.

    Шаг 2 - Обрабатываем HTTP ответ

    Отправляя запрос, вы указали имя функции JavaScript, обрабатывающей ответ.

    http_request.onreadystatechange = nameOfTheFunction;

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

    if (http_request.readyState == 4) {
    // все в порядке, ответ получен
    } else {
    // все еще не готово
    }

    Полный список значений кодов readyState такой:

    * 0 (uninitialized)
    * 1 (loading)
    * 2 (loaded)
    * 3 (interactive)
    * 4 (complete)

    Следующее, что нужно проверить - это статус HTTP-ответа. Все возможные коды можно посмотреть на сайте W3C . Для наших целей нам интересен только код ответа 200 OK.

    if (http_request.status == 200) {
    // великолепно!
    } else {
    // с запросом возникли проблемы,
    // например, ответ может быть 404 (Не найдено)
    // или 500 (Внутренняя ошибка сервера)
    }

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

    * http_request.responseText – возвращает ответ сервера в виде строки текста.
    * http_request.responseXML – возвращает ответ сервера в виде объекта XMLDocument, который вы можете обходить используя функции JavaScript DOM

    Шаг 3 - Простой пример

    Давайте соберем все вместе и сделаем простой пример HTTP-запроса. Наш JavaScript запросит HTML документ test.html, который содержит текст "I"m a test." и выведет содержимое файла в диалоговом окне.


    function makeRequest(url) {
    var http_request = false;
    if (window.XMLHttpRequest) { // Mozilla, Safari, ...
    http_request = new XMLHttpRequest();
    if (http_request.overrideMimeType) {
    http_request.overrideMimeType("text/xml");
    // Читайте ниже об этой строке
    }
    } else if (window.ActiveXObject) { // IE
    try {
    http_request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
    try {
    http_request = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e) {}
    }
    }
    if (!http_request) {
    alert("Не вышло:(Невозможно создать экземпляр класса XMLHTTP ");
    return false;
    }
    http_request.onreadystatechange = function() { alertContents(http_request); };
    http_request.open("GET", url, true);
    http_request.send(null);
    }
    function alertContents(http_request) {



    } else {

    }
    }
    }


    Сделать запрос

    В этом примере:

    * Пользователь нажимает на ссылку "Сделать запрос" в броузере;
    * Это вызывает функцию makeRequest() с параметром test.html - именем HTML файла;
    * Посылается запрос, после чего (onreadystatechange) выполнение передается alertContents();
    * alertContents() проверяет получен ли ответ и все ли с ним в порядке, после чего содержимое файла test.html выводится в диалоговом окне.

    Вы можете попробовать пример в действии , а сам тестовый файл можно посмотреть .

    Замечание: Строка http_request.overrideMimeType("text/xml"); вызовет ошибки в консоли JavaScript в Firefox 1.5 или более позднем, как описано в https://bugzilla.mozilla.org/show_bug.cgi?id=311724 , если страница вызванная с помощью XMLHttpRequest не является правильным XML (например, если это обычный текст). На самом деле это корректное поведение.

    Замечание 2: Если вы посылаете запрос не на статический XML-файл, а на серверный скрипт, возвращающий XML, то нужно установить некоторые заголовки ответа, если вы планируете сделать вашу страницу работоспособной в Internet Explorer помимо Mozilla. Если вы не установите заголовок Content-Type: application/xml, IE будет сообщать об ошибке JavaScript, "Object Expected", после строки, где вы пытаетесь получить доступ к XML элементу. Если вы не установите заголовок Cache-Control: no-cache броузер будет кэшировать ответ и никогда не будет повторно отправлять запрос, что сделает отладку весьма «забавной».

    Замечание 3: Если переменная http_request используется глобально, то конкурирующие функции, вызывающие makeRequest() могут конкурировать друг с другом, вызывая состязания. Объявление переменной http_request локально в функции и передача ее в alertContent() предотвращает состязания.

    Замечание 4: При привязывании функции обратного вызова к onreadystatechange нельзя указывать аргументов. По этой причине не работает следующий код:

    http_request.onreadystatechange = alertContents(http_request); // (не работает)

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

    http_request.onreadystatechange = function() { alertContents(http_request); }; //1 (одновременный запрос)
    http_request.onreadystatechange = alertContents; //2 (глобальная переменная)

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

    Замечание 5: В случае ошибки взаимодействия (например, если сервер упал), при попытке доступа к переменной.status метода onreadystatechange будет сгенерировано исключение. Убедитесь, что if...then заключено в try...catch. (См. https://bugzilla.mozilla.org/show_bug.cgi?id=238559).

    function alertContents(http_request) {
    try {
    if (http_request.readyState == 4) {
    if (http_request.status == 200) {
    alert(http_request.responseText);
    } else {
    alert("С запросом возникла проблема.");
    }
    }
    }
    catch(e) {
    alert("Произошло исключение: " + e.description);
    }
    }

    Шаг 4 - Работа с XML ответом
    В предыдущем примере, после того как был получен ответ на HTTP-запрос мы использовали responseText запрашиваемого объекта, который содержал данные файла test.html. Теперь давайте попробуем использовать свойство responseXML.

    Прежде всего, давайте создадим правильный XML документ, который мы будем запрашивать. Документ (test.xml) содержит следующее:

    < ?xml version="1.0" ?>

    I"m a test.

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

    ...
    onclick="makeRequest("test.xml")">
    ...

    var xmldoc = http_request.responseXML;
    var root_node = xmldoc.getElementsByTagName("root").item(0);
    alert(root_node.firstChild.data);

    Чтобы узнать больше о методах DOM, посмотрите

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

    Примечание. Если Вы не знаете основы JavaScript, и не можете понять простой код на JavaScript, советую, для начала, прочитать вот эти статьи "JavaScript для начинающих – Простые примеры " и "JavaScript – Пример расширения формы регистрации " ,так как без знаний JavaScript учить AJAX бессмысленно!

    Что такое AJAX?

    AJAX (Asynchronous JavaScript and XML ) - асинхронный JavaScript и XML, это механизм взаимодействия с сервером, посредствам которого происходит обмен данными с этим сервером, не перезагружая всю страницу целиком. Запрос на AJAX может быть не только асинхронный, но и просто синхронным, но такие запросы используются редко. Так как при таких запросах браузер зависает, до того момента пока не будет получен ответ с сервера, в отличие от асинхронного запроса, при котором посылается запрос и пользователь может делать на странице все что угодно, а когда будет получен ответ от сервера, сработает обработчик и появятся изменения на странице. Как посылать синхронные и асинхронные запросы научимся ниже в примерах.

    Для чего нужен AJAX?

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

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

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

    Недостатки AJAX

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

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

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

    Хватит теории, перейдем к практике. Сразу скажу, что ajax - это не сложно, и если Вы разобрались с JavaScript, то разобраться с ajax будет очень просто, даже легче чем с JavaScript!

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

    Весь механизм начинается с создания этого объекта, и создать его можно по-разному, в старых браузерах это делается одним способом, а во всех новых другим способом. Если вдруг Вы не планируете использовать ajax на старых браузерах, например, Вы создаете ajax-приложение для корпоративной сети, в которой установлены современные браузеры, Вы можете смело создать этот объект одной строкой:

    Var request = new XMLHttpRequest();

    где, в переменной request и будет храниться наш объект.

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

    Function getXmlHttpRequest() { if (window.XMLHttpRequest) { try { return new XMLHttpRequest(); } catch (e){} } else if (window.ActiveXObject) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e){} try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e){} } return null; }

    Для создания объекта XMLHttpRequest мы просто вызовем функцию getXmlHttpRequest, которая вернет нам нужный объект.

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

    Для того чтобы наш урок прошел полноценно, нам потребуется небольшой серверный скрипт, я буду использовать серверный язык программирования PHP, и наш скрипт будет просто возвращать текущие время на сервере. Назовем его mytime.php, его код:

    Код mytime.php:

    Здесь я думаю все понятно, мы проверяем параметр, пришедший к нам методом GET, т.е. MyTime, и если параметр действительно к нам пришел, то возвращаем текущие время на сервере. Советую при разработке ajax приложения на серверном скрипте делать больше проверок, так как ajax запрос можно подделать. Можно делать вот такие проверки, например:

    • можно дополнительно посылать заголовок X-REQUESTED-WITH , а на серверном обработчике проверять его;
    • также добавить проверку реферера, т.е. откуда пришел запрос;
    • еще можно осуществлять проверку с помощью сессий.

    Код index.php:

    //функция создания объекта XMLHttpRequest function getXmlHttpRequest(){ if (window.XMLHttpRequest) { try { return new XMLHttpRequest(); } catch (e){} } else if (window.ActiveXObject) { try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e){} try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e){} } return null; } function serverTime(){ // Объект XMLHttpRequest var request = getXmlHttpRequest(); /*свойство onreadystatechange это обработчик события, которое реагирует на любое изменения данного объекта*/ request.onreadystatechange = function (){ /*свойство readyState - состояние объекта 0 - не инициализирован 1 - открыт, 2 - отправка данных, 3 - получение данных, 4 - данные загружены рекомендую использовать только 4*/ if (request.readyState == 4) { /*свойство status это HTTP-статус ответа: 200-OK, 404-Not Found*/ if (request.status == 200){ var result = document.getElementById("MyId"); // Чтение ответа result.firstChild.nodeValue = request.responseText; // Вывод на экран } else document.write("Произошла ошибка. Обнови страничку"); } } // Адрес серверного скрипта var url = "mytime.php?MyTime"; /* Запрос на сервер, true означает что это асинхронный запрос если было бы false, то это синхронный запрос*/ request.open("GET", url, true); request.setRequestHeader("Content-type", "charset=utf8"); request.send(null); // посыл данных }

    Вот два файла (mytime.php и index.php ), с помощью которых Вы легко можете проверить работу ajax, код этих файлов представлен выше.

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

    Код функции serverTime с передачей параметров методом post:

    Function serverTime(){ var request = getXmlHttpRequest(); request.onreadystatechange = function (){ if (request.readyState == 4) { if (request.status == 200){ var result = document.getElementById("MyId"); result.firstChild.nodeValue = request.responseText; } else document.write("Произошла ошибка. Обнови страничку"); } } var url = "mytime2.php";//изменим адрес серверного обработчика var data = "MyTime=1";//задаем параметры request.open("POST", url, true); // указываем метод post //посылаем два заголовка: тип данных и размер данных request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.setRequestHeader("Content-Length", data.length); request.send(data); // посыл данных, вместо null вставляем переменную с параметрами }

    Не забудьте изменить серверный обработчик, чтобы он проверял данные пришедшие методом post. Измените строку isset($_GET["MyTime"] на isset($_POST["MyTime"] и все будет работать точно так же, как и с помощью GET.

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

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

    AJAX - это аббревиатура, которая означает Asynchronous Javascript and XML. На самом деле, AJAX не является новой технологией, так как и Javascript, и XML существуют уже довольно продолжительное время, а AJAX - это синтез обозначенных технологий. AJAX чаще всего ассоцириуется с термином Web 2.0 и преподносится как новейшее Web-приложение.

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

    Обобщим достоинства AJAX:

    • Возможность создания удобного Web-интерфейса
    • Активное взаимодействие с пользователем
    • Удобство использования
    AJAX использует два метода работы с веб-страницей: изменение Web-страницы не перезагружая её, и динамическое обращение к серверу. Второе может осуществляться несколькими способами, в частности, XMLHttpRequest, о чем мы и будем говорить, и использование техники скрытого фрейма.Обмен данными

    Для того, чтобы осуществлять обмен данными, на странице должен быть создан объект XMLHttpRequest, который является своеобразным посредником между Браузером пользователя и сервером (рис. 1). С помощью XMLHttpRequest можно отправить запрос на сервер, а также получить ответ в виде различного рода данных.

    Обмениваться данными с сервером можно двумя способами. Первый способ - это GET-запрос. В этом запросе вы обращаетесь к документу на сервере, передавая ему аргументы через сам URL. При этом на стороне клиента будет логично использовать функция Javascript`а escape для того, чтобы некоторые данные не прервали запрос.

    Клиент часть, написанная на Javascript, должна обеспечивать необходимую функциональность для безопасного обмена с сервером и предоставлять методы для обмена данными любым из вышеперечисленных способов. Серверная часть должна обрабатывать входные данные, и на основе их генерировать новую информацию (например, работая с базой данных), и отдавать ее обратно клиенту. Например, для запроса информации с сервера можно использовать обычный GET-запрос с передачей нескольких и небольших по размеру параметров, а для обновления информации, или добавления новой информации потребуется использовать уже POST-запрос, так как он позволяет передавать большие объемы данных.

    Как уже было сказано, AJAX использует асинхронную передачу данных. Это значит, что пока идёт передача данных, пользователь может совершать другие, необходимые ему действия. В это время следует оповестить пользователя о том, что идёт какой-либо обмен данными, иначе пользователь подумает, что произошло что-то не то и может покинуть сайт, или повторно вызвать «зависшую», по его мнению, функцию. Индикация во время обмена данными в приложении Web 2.0 играет очень важную роль: посетители могли еще не привыкнуть к таким способам обновления страницы.

    Ответ от сервера может быть не только XML, как следует из названия технологии. Помимо XML, можно получить ответ в виде обычного текста, или же JSON (Javascript Object Notation). Если ответ был получен простым текстом, то его можно сразу вывести в контейнер на странице. При получении ответа в виде XML, обычно происходит обработка полученного XML документа на стороне клиента и преобразование данных к (X)HTML. При получении ответа в формате JSON клиент должен лишь выполнить полученный код (функция Javascript`а eval) для получения полноценного объекта Javascript. Но здесь нужно быть осторожным и учитывать тот факт, что с использованием этой технологии может быть передан вредоносный код, поэтому перед выполнением полученного с сервера кода следует его тщательно проверить и обработать. Существует такая практика, как «холостой» запрос, при котором никакой ответ от сервера не приходит, лишь изменяются данные на стороне сервера.

    В разных браузерах данный объект обладает разными свойствами, но в целом он совпадает.

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

    Заметьте, что названия методов записаны в том же стиле (Camel-style), что и другие функции Javascript. Будьте внимательны при их использовании.

    abort() - отмена текущего запроса к серверу.

    getAllResponseHeaders() - получить все заголовки ответа от сервера.

    getResponseHeader(«имя_заголовка») - получить указаный заголовок.

    open(«тип_запроса»,«URL»,«асинхронный»,«имя_пользователя»,«пароль») - инициализация запроса к серверу, указание метода запроса. Тип запроса и URL - обязательные параметры. Третий аргумент - булево значение. Обычно всегда указывается true или не указывается вообще (по умолчанию - true). Четвертый и пятый аргументы используются для аутентификации (это очень небезопасно, хранить данные об аутентификации в скрипте, так как скрипт может посмотреть любой пользователь).

    send(«содержимое») - послать HTTP запрос на сервер и получить ответ.

    setRequestHeader(«имя_заголовка»,«значение») - установить значения заголовка запроса.

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

    onreadystatechange - одно из самых главных свойств объекта XMLHttpRequest. С помощью этого свойства задаётся обработчик, который вызывается всякий раз при смене статуса объекта.

    readyState - число, обозначающее статус объекта.

    responseText - представление ответа сервера в виде обычного текста (строки).

    responseXML - объект документа, совместимый с DOM, полученного от сервера.

    status - состояние ответа от сервера.

    statusText - текстовое представление состояния ответа от сервера.

    Следует подробнее расммотреть свойство readyState:

    • 0 - Объект не инициализирован.
    • 1 - Объект загружает данные.
    • 2 - Объект загрузил свои данные.
    • 3 - Объек не полностью загружен, но может взаимодействовать с пользователем.
    • 4 - Объект полностью инициализирован; получен ответ от сервера.
    Именно опираясь на состояние готовности объекта можно представить посетителю информацию о том, на какой стадии находится процесс обмена данными с сервером и, возможно, оповестить его об этом визуально.Создание объекта XMLHttpRequest

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

    Например, для создания объекта в Gecko-совместимых браузерах, Konqueror`е и Safari, нужно использовать следующее выражение:

    Var Request = new XMLHttpRequest();

    А для Internet Explorer`а используется следующее:

    Var Request = new ActiveXObject("Microsoft.XMLHTTP");

    Var Request = new ActiveXObject("Msxml2.XMLHTTP");

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

    Function CreateRequest() { var Request = false; if (window.XMLHttpRequest) { //Gecko-совместимые браузеры, Safari, Konqueror Request = new XMLHttpRequest(); } else if (window.ActiveXObject) { //Internet explorer try { Request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (CatchException) { Request = new ActiveXObject("Msxml2.XMLHTTP"); } } if (!Request) { alert("Невозможно создать XMLHttpRequest"); } return Request; }

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

    Запрос к серверу

    Алгоритм запроса к серверу выглядит так:

    • Проверка существования XMLHttpRequest.
    • Инициализация соединения с сервером.
    • Посылка запрса серверу.
    • Обработка полученных данных.
    Для создания запроса к серверу мы создадим небольшую функцию, которая будет по функциональности объединять в себе функции для GET и POST запросов.

    /* Функция посылки запроса к файлу на сервере r_method - тип запроса: GET или POST r_path - путь к файлу r_args - аргументы вида a=1&b=2&c=3... r_handler - функция-обработчик ответа от сервера */ function SendRequest(r_method, r_path, r_args, r_handler) { //Создаём запрос var Request = CreateRequest(); //Проверяем существование запроса еще раз if (!Request) { return; } //Назначаем пользовательский обработчик Request.onreadystatechange = function() { //Если обмен данными завершен if (Request.readyState == 4) { //Передаем управление обработчику пользователя r_handler(Request); } } //Проверяем, если требуется сделать GET-запрос if (r_method.toLowerCase() == "get" && r_args.length > 0) r_path += "?" + r_args; //Инициализируем соединение Request.open(r_method, r_path, true); if (r_method.toLowerCase() == "post") { //Если это POST-запрос //Устанавливаем заголовок Request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=utf-8"); //Посылаем запрос Request.send(r_args); } else { //Если это GET-запрос //Посылаем нуль-запрос Request.send(null); } }

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

    Function ReadFile(filename, container) { //Создаем функцию обработчик var Handler = function(Request) { document.getElementById(container).innerHTML = Request.responseText; } //Отправляем запрос SendRequest("GET",filename,"",Handler); }

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

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

    В предыдущем примере мы сделали функцию запроса к серверу. Но она, по сути, небезопасна, так как мы не обрабатываем состояния объекта и состояния ответа от сервера.

    Дополним наш код, чтобы он смог выводить визуальное оповещение о процессе загрузки.

    Request.onreadystatechange = function() { //Если обмен данными завершен if (Request.readyState == 4) { //Передаем управление обработчику пользователя r_handler(Request); } else { //Оповещаем пользователя о загрузке } } ...

    Как вы уже знаете, объект XMLHttpRequest позволяет узнать статус ответа от сервера. Воспользуемся этой возможностью.

    Request.onreadystatechange = function() { //Если обмен данными завершен if (Request.readyState == 4) { if (Request.status == 200) { //Передаем управление обработчику пользователя r_handler(Request); } else { //Оповещаем пользователя о произошедшей ошибке } } else { //Оповещаем пользователя о загрузке } } ...

    Варианты ответа от сервера

    От сервера можно получить данные нескольких видов:

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

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

    Пример кода JSON:
    { "data": { "misc": [ { "name" : "JSON-элемент один", "type" : "Подзаголовок 1" }, { "name" : "JSON-элемент два", "type" : "Подзаголовок 2" } ] } }

    При получении такого кода, производим следующее действие:

    Var responsedata = eval("(" + Request.responseText + ")")

    После выполнения данного кода вам будет доступен объект responsedata .

    Работа с серверными языками программирования

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

    По традиции, начнем с приветствия нашему замечательному миру:

    Echo "Hello, World!";

    При обращении к этому файлу клиенту вернется строка Hello, World. Как вы понимаете, это представляет широчайшие возможности для построения приложений. На основе передачи аргументов при вызове сервера с помощью XMLHttpRequest можно сделать параметризацию вывода, тем самым обеспечив обширную функциональность Web-приложения.

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