Создаем класс для ajax запросов

Предлагаю сегодня построить класс, который бы упростил нашу работу с AJAX-запросами. Класс будем реализовывать с помощью объектов XMLHttpRequest.


Задача
Реализовать класс, позволяющий совершать параметризированные ajax запросы методами post и get.

ajax, ты кто такой?
Прежде, чем перейти к, собственно, описанию реализации класса, было бы неплохо понять, что же такое ajax.
ajax, грубо говоря, технология, которая позволяет работать с веб-сервисом в фоновом режиме, то есть, без перезагрузки веб-страницы. Вследствие этого, работа веб приложений выглядит как «обработка» в реальном времени и затрачивает меньше времени на обработку. (так как не перезагружается вся страница)
Следует также упомянуть, что Ajax ни в коем случае не является самостоятельной технологией.
На мой взгляд ajax можно определить как идея работы с веб-сервисом.
Одной из реализаций данной идеи и является динамический запрос и получение данных посредством XMLHttpRequest.

Структура класса
В классе будут определены следующие методы:
Конструктор: инициализирует такие данные как:
  • callback = функция callback (функция, которая будет вызвана по получению (Response) ответа с сервера) – установлена в null

  • request = Объект класса XMLHttpRequest – так как уже актуален браузер IE10, который, по моему скромному мнению, является весьма неплохим и поддерживающий создание данных объектов без заморочек, не будем делать совместимость с ранними версиями. Если кому-то будет интересно, как сделать совместимый класс – с радостью расскажу в комментариях.

  • params = Параметры запроса – также установлен по умолчанию в null

Затем определим следующие функции:
SetParamsToQuery – принимает на вход список параметров, записывает их в массив параметров запроса. В данной функции воспользуемся замечательной возможностью JavaScript принимать любое количество аргументов и записывать их в массив arguments, что избавляет нас от организации структур данных на считывание параметров.
Выглядит данная функция следующим образом:
  1. this. SetParamsToQuery = function()
  2.    {
  3.      params = [];
  4.      for (var i = 0 ; i < arguments.length; i+=2) {
  5.         params.push(arguments[i] + "=" + arguments[i + 1 ]);
  6.      }
  7.    }

This code was highlighted with code.xnim.ru

Следующая функция – обработка ответа сервера (на самом деле с ее помощью мы можем обрабатывать состояния сервера, но мы воспользуемся только событием, когда уже весь ответ был принят) Данная функция будет проверять readyState переменной request, и если эта переменная равна 4, то запрос завершил свое выполнение. Затем проверим статус и если он есть ОК (200), то вызовем определенную пользователем функцию обработки, параметром которой укажем ответ сервера:
  1. function STDReadyStateChange()
  2.    {
  3.      if (request.readyState == 4 )
  4.      {
  5.        if (request.status == 200 )
  6.         {
  7.            callBack(request.responseText);
  8.         }
  9.        else
  10.          {
  11.            callBack("Не могу получить ответ от сервера." );
  12.         }
  13.      }
  14.    }

This code was highlighted with code.xnim.ru

Как можно заметить данная функция является недоступной извне.
Следующая функция устанавливает callBack-функцию пользователя:
  1. //Установка CallBack функции
  2.    this.SetCallBack = function (callBackUserFunction) {
  3.      callBack = callBackUserFunction;
  4.    }

This code was highlighted with code.xnim.ru

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

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

<Параметр>=<значение>&<параметр2>=<значение2>

Данная запись означает, что очередное значение будет прочитано только до символа &. А если данный символ встречается в значении? Это означает, что остальная часть строки будет признана началом нового параметра и т.д. -> неверная передача данных.
Избавиться от данной проблемы довольно просто, достаточно заменить все символы & на его числовое значение %26.
Это же справедливо для POST запросов.

POST и GET
Вначале приведу их код, а затем разберем его.
  1. this.Post = function( url) {
  2.         request.open("POST" , url, true) ;
  3.         request.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded" );
  4.         request.onreadystatechange = STDReadyStateChange;
  5.          for (var i = 0 ; i <params.length; i++)
  6.          {
  7.             params[i] = params[i].replace(''&'' ,''%26 '')
  8.          }
  9.         request.send(params.join("&" ));
  10.      }
  11.   
  12.    this.Get = function (url) {
  13.      request.open("GET" , url, true) ;
  14.       request.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded" );
  15.      request.onreadystatechange = STDReadyStateChange;
  16.       for (var i = 0 ; i <params.length; i++)
  17.          {
  18.             params[i] = params[i].replace(''&'' ,''%26 '')
  19.          }
  20.      request.send(params.join("&" ));
  21.    }

This code was highlighted with code.xnim.ru

Разберем только одну из функций, так как другая отлична только методом.
Первым действием мы указываем метод, url на который будем отправлять запрос и метку асинхронного запроса (true). Запрос используем асинхронный, так как при синхронном запросе при его «повисании» мы блокируем все последующее выполнение скрипта. Используются синхронные запросы только в САМЫХ крайних случаях.
Затем установим заголовок запроса и callback функцию (ту самую внутреннюю функцию класса)
После этого заменим во всех параметрах & на %26 и отправим запрос, превратив массив в строку с помощью метода join(‘&’) . Остается только дождаться(читать либо дальше выполнять свой скрипт, либо уже все выполнено, ничего не происходит) ответа от сервера и выполняться начнет callBack функция.

Полный код
Приведу полный код данного класса:
  1. //Конструктор
  2. function Ajax()
  3. {
  4.    //Пост функция
  5.    //(требования к данной функции - она должна принимать 1 параметр, дабы получить ответ сервера)
  6.    var callBack = null;
  7.   
  8.    var request = new XMLHttpRequest();
  9.    var params = null;
  10.    //Принимает на вход список параметров, обрабатывает и выдает данные для запроса.
  11.    //Формат данных массив, где 2 k-й элемент ключ, 2 k+1 -й элемент - значение
  12.    //Пример - [ключ1, значение1, ключ2, значение2]
  13.    this.SetParamsToQuery = function( )
  14.    {
  15.      params = [];
  16.      for (var i = 0 ; i < arguments.length; i+=2) {
  17.         params.push(arguments[i] + "=" + arguments[i + 1 ]);
  18.      }
  19.    }
  20.    //Стандартный пост обработчик запросов
  21. function STDReadyStateChange()
  22.    {
  23.      if (request.readyState == 4 )
  24.      {
  25.        if (request.status == 200 )
  26.         {
  27.            callBack(request.responseText);
  28.         }
  29.        else
  30.          {
  31.            callBack("Не могу получить ответ от сервера." );
  32.         }
  33.      }
  34.    }
  35.    
  36.    //Установка CallBack функции
  37.    this.SetCallBack = function (callBackUserFunction) {
  38.      callBack = callBackUserFunction;
  39.    }
  40.    this.Post = function( url) {
  41.         request.open("POST" , url, true) ;
  42.         request.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded" );
  43.         request.onreadystatechange = STDReadyStateChange;
  44.          for (var i = 0 ; i <params.length; i++)
  45.          {
  46.             params[i] = params[i].replace(''&'' ,''%26 '')
  47.          }
  48.         request.send(params.join("&" ));
  49.      }
  50.   
  51.    this.Get = function (url) {
  52.      request.open("GET" , url, true) ;
  53.       request.setRequestHeader("Content-Type" , "application/x-www-form-urlencoded" );
  54.      request.onreadystatechange = STDReadyStateChange;
  55.       for (var i = 0 ; i <params.length; i++)
  56.          {
  57.             params[i] = params[i].replace(''&'' ,''%26 '')
  58.          }
  59.      request.send(params.join("&" ));
  60.    }
  61. };

This code was highlighted with code.xnim.ru

Класс готов. Теперь приведу пример использования данного кода:
  1. //Отправляет запрос на получение страницы с комментариями. Получет результат.
  2. function GetSomeInfo(index) {
  3. //создаем объект класса
  4.    var InfoRequest = new Ajax();
  5.    //устанавливаем коллбек
  6.    PageRequest.SetCallBack(function (result) {
  7.    //пусть полученная информация будет отображена как html в контейнере с id = MyInfo
  8.      document.getElementById("MyInfo" ).innerHTML = result;
  9.    });
  10.    //устанавливаем параметры. Если их больше двух, то запрос бы был:
  11.    //PageRequest.SetParamsToQuery("id" , index,''id2'',index+4 и так далее);
  12.    PageRequest.SetParamsToQuery("id" , index) ;
  13.    PageRequest.Post("http://someSite.com/index.php" );
  14. }

This code was highlighted with code.xnim.ru

Задача создания ajax запросов стала проще. Неправда ли? (:

Еще проще!
Теперь предлагаю отойти от создания своего класса и задаться вопросом – а есть ли уже способ создавать такие запросы намного проще?
Ответ на данный вопрос смело даем утвердительный.
JQuery позволяет создавать такие запросы одной строкой – для этого существует метод $.ajax () http://api.jquery.com/jQuery.ajax/, $.post() , либо $.get()
Приведу пример нашего запроса посредством JQuery:
  1. jQuery.post("http://someSite.com/index.php" ,
  2. {id : index}, function (result) {
  3.    //пусть полученная информация будет отображена как html в контейнере с id = MyInfo
  4.      document.getElementById("MyInfo" ).innerHTML = result;
  5.    });

This code was highlighted with code.xnim.ru

Надеюсь, что данный материал был интересен и в чем-то полезен Вам.
2013-01-31