AJAX - Асинхронные запросы на примерах

Урок, в котором на примерах рассмотрим создание простых асинхронных AJAX запросов к серверу. В качестве метода передачи запросов будем использовать как метод GET, так и метод POST. На сервере обработку запросов выполним с помощью скриптов PHP.

Что такое асинхронный запрос AJAX?

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

При отправке асинхронного запроса, браузер (страница) не "замораживается", т.е. с ней, как и прежде, можно работать. Но тогда как узнать, когда придёт ответ с сервера. Чтобы это определить, необходимо отслеживать свойство браузера readyState (состояние готовности). Данное свойство содержит число, по значению которого можно судить о том, в какой стадии находится запрос. В следующей таблице приведены основные значения свойства readyState и соответствующие им состояния.

Значение свойства readyState Описание
0 запрос не инициализирован
1 выполнена настройка запроса
2 запрос отправлен
3 запрос находится в процессе обработки на сервере
4 запрос завершён

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

Для того чтобы определить на какой стадии находится запрос, необходимо использовать событие объекта XMLHttpRequest onreadystatechange. Данное событие происходит каждый раз, когда изменяется значение свойства readyState. Следовательно, в обработчике этого события (неименованной или именованной функции) можно прописать действия, которые будут проверять равно ли данное свойство 4 и если равно, то например, вывести ответ сервера на страницу.

Схема работы AJAX (асинхронный запрос)
Схема работы AJAX (асинхронный запрос)

Создание асинхронного AJAX запроса (метод GET)

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

Для этого необходимо создать на сервере 2 файла в одном каталоге:

  1. welcome.html – HTML-страница, которая будет отображаться пользователю. В этой же страницы поместим скрипт, который будет осуществлять все необходимые действия для работы AJAX на стороне клиента.
  2. processing.php – PHP-файл, который будет обрабатывать запрос на стороне сервера, и формировать ответ. Начнём разработку с создания основной структуры файла welcome.html
<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>
  <div id="welcome"></div>
  <script>
  // Здесь поместим код JavaScript, который будет отправлять запрос на сервер, получать его и обновлять содержимое страницы. Всё это будет работать без перезагрузки страницы

</script>
</body>
</html>  

Рассмотрим последовательность действий, которые необходимо выполнить на стороне клиента (в коде JavaScript):

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

  2. Создадим переменную, которая будет содержать экземпляр объекта XHR (XMLHttpRequest).

  3. Настроим запрос с помощью метода open().

    Указываются следующие параметры:

    • Метод, с помощью которого будет посылаться запрос на сервер (GET, POST).
    • URL-адрес, который будет обрабатывать запрос на сервере.
    • Тип запроса: синхронный (false) или асинхронный (true).
    • Имя и пароль при необходимости.
  4. Подпишемся на событие onreadystatechange объекта XHR и укажем обработчик в виде анонимной или именованной функции. После этого создадим код внутри этой функции, который будет проверять состояние ответа, и выполнять определённые действия на странице. Ответ, который приходит с сервера, всегда находится в свойстве responseText.

    Дополнительно с проверкой значения свойства readyState числу 4, можно проверять и значение свойства status. Данное свойство определяет статус запроса. Если оно равно 200, то всё OK. А иначе произошла ошибка (например, 404 – URL не найден).

  5. Отправим запрос на сервер с помощью метода send().

    Если используем для отправки запроса метод GET, то передавать данные в параметр данного метода не надо. Они передаются в составе URL.

    Если используем для отправки запроса метод POST, то данные необходимо передать в качестве параметра методу send(). Кроме этого, перед вызовом данного метода необходимо установить заголовок Content-Type, чтобы сервер знал в какой кодировке пришёл к нему запрос и смог его расшифровать.

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

// 2. Создание переменной request
var request = new XMLHttpRequest();
// 3. Настройка запроса
request.open('GET','processing.php',true);
// 4. Подписка на событие onreadystatechange и обработка его с помощью анонимной функции
request.addEventListener('readystatechange', function() {
  // если состояния запроса 4 и статус запроса 200 (OK)
  if ((request.readyState==4) && (request.status==200)) {
    // например, выведем объект XHR в консоль браузера
    console.log(request);
    // и ответ (текст), пришедший с сервера в окне alert
    console.log(request.responseText);
    // получить элемент c id = welcome
    var welcome = document.getElementById('welcome');
    // заменить содержимое элемента ответом, пришедшим с сервера
    welcome.innerHTML = request.responseText;
  }
}); 
// 5. Отправка запроса на сервер
request.send();

В итоге файл welcome.html будет иметь следующий код:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>

  <div id="welcome"></div>

<script>
window.addEventListener("load",function() {
  var request = new XMLHttpRequest();
  request.open('GET','processing.php',true);
  request.addEventListener('readystatechange', function() {
    if ((request.readyState==4) && (request.status==200)) {
      var welcome = document.getElementById('welcome');
      welcome.innerHTML = request.responseText;
    }
  });
request.send();
});
</script>

</body>
</html>

На сервере (с помощью php):

  1. Получим данные. Если данные посланы через метод GET, то из глобального массива $_GET['имя']. А если данные переданы с помощью метода POST, то из глобального массива $_POST['имя'].
  2. Используя эти данные, выполним некоторые действия на сервере. В результате которых получим некоторый ответ. Выведем его с помощью echo.
<?php
$output = 'Здравствуйте, пользователь! ';
if ($_SERVER['REMOTE_ADDR']) {
  $output .= 'Ваш IP адрес: '. $_SERVER['REMOTE_ADDR'];
}
else {
 $output .= 'Ваш IP адрес неизвестен.';
}
echo $output;
HTML-страница, на которую пришёл AJAX ответ с сервера (метод GET)
HTML-страница, на которую пришёл AJAX ответ с сервера (метод GET)

Создание асинхронного AJAX запроса (метод POST)

Изменим вышеприведённый пример. Теперь AJAX запрос к серверу будет выполняться после нажатию на кнопку. Он будет получать имя, которое ввёл пользователь в элемент input и отправлять его посредством метода POST на сервер. После получения ответа с сервера, заменим им содержимое элемента div на странице.

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8">
  <title>Пример работы AJAX</title>
</head>
<body>
  <h1>Пример работы AJAX</h1>

  <div id="welcome">
    <label for="name">Имя:</label>
    <input type="text" id="name" placeholder="Например, Иван">
    <button id="send">Отправить</button>
  </div>

<script>
//после загрузки DOM-дерева страницы
document.addEventListener("DOMContentLoaded",function() {
  //получить кнопку
  var mybutton = document.getElementById('send');
  //подписаться на событие click по кнопке и назначить обработчик, который будет выполнять действия, указанные в безымянной функции
  mybutton.addEventListener("click", function(){
    //1. Сбор данных, необходимых для выполнения запроса на сервере
    var name = document.getElementById('name').value;
    //Подготовка данных для отправки на сервер
    //т.е. кодирование с помощью метода encodeURIComponent
    name = 'nameUser=' + encodeURIComponent(name);
    // 2. Создание переменной request
    var request = new XMLHttpRequest();
    // 3. Настройка запроса
    request.open('POST','processing.php',true);
    // 4. Подписка на событие onreadystatechange и обработка его с помощью анонимной функции
    request.addEventListener('readystatechange', function() {
      //если запрос пришёл и статус запроса 200 (OK)
      if ((request.readyState==4) && (request.status==200)) {
        // например, выведем объект XHR в консоль браузера
        console.log(request);
        // и ответ (текст), пришедший с сервера в окне alert
        console.log(request.responseText);
        // получить элемент c id = welcome
        var welcome = document.getElementById('welcome');
        // заменить содержимое элемента ответом, пришедшим с сервера
        welcome.innerHTML = request.responseText;
      }
    });
    // Устанавливаем заголовок Content-Type(обязательно для метода POST). Он предназначен для указания кодировки, с помощью которой зашифрован запрос. Это необходимо для того, чтобы сервер знал как его раскодировать.
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    // 5. Отправка запроса на сервер. В качестве параметра указываем данные, которые необходимо передать (необходимо для POST)
    request.send(name);
  });
});
</script>

</body>
</html>
<?php
// создадим переменную для формирования ответа
$output ='';
// если в массиве пост есть ключ nameUser, то
if (isset($_POST['nameUser'])) {
  // в переменную name помещаем переданное с помощью запроса имя
  $name = $_POST['nameUser'];
  // добавляем в переменную output строку приветствия с именем
  $output .= 'Здравствуйте, '.$name.'! ';
  // добавляем в переменную output IP-адрес пользователя
  if ($_SERVER['REMOTE_ADDR']) {
    $output .= 'Ваш IP адрес: '. $_SERVER['REMOTE_ADDR'];
  }
  else {
   $output .= 'Ваш IP адрес неизвестен.';
  }
  // выводим ответ
  echo $output;
}
HTML-страница с AJAX (метод POST)
HTML-страница с AJAX (метод POST)
HTML-страница, на которую пришёл AJAX ответ с сервера (метод POST)
HTML-страница, на которую пришёл AJAX ответ с сервера (метод POST)


   JavaScript и jQuery 0    2519 0

Комментарии (3)

  1. Евгений # 0
    Добрый день.
    Большое спасибо за статью!
    А где бы посмотреть подгрузку информации при прокрутке страницы? Т.е. например листаем вниз, добавляются новые посты.
    1. Александр Мальцев # 0
      Здравствуйте.
      Тут необходимо завести переменную, которая будет отвечать за то, находится ли AJAX запрос в обработке или нет. Например, processing. Т.е. если при прокрутке страницы, значение переменной равно false, то загружаем данные. На момент загрузки данных устанавливаем значение переменной processing, равной true. Это необходимо сделать для того чтобы не сделать кучу запросов пока данные не пришли. Как только данные пришли, устанавливаем переменной значение false и готовы к загрузке новой партии данных с сервера. Другими словами, данная переменная необходима для того чтобы при прокрутке Вы не сделали 1000 запрос к серверу, а только один.

      Для простоты приведу решение на jQuery, пояснив каждую строчку кода. Для загрузки данных будем использовать содержимое файла data.txt. Т.е. при прокрутке страницы более чем на 80%, берём данные из файла data.txt и помещаем их в блок div.

      <!-- Контейнер, в который будут подгружаться данные из файла data.txt -->
      <div id="container"></div>
      
      <script>
      // переменная, отвечаяющая за то находится ли в процесс в получение данных с помощью AJAX
      var processing;
      // после загрузки страницы
      $(document).ready(function(){
        // при прокрутке страницы
        $(document).scroll(function(e){
          // если процесс находится в обработке (т.е. ещё не данные не пришли), то ничего не делать
          if (processing)
            return false;
          // если пользователь прокрутил страницу более чем на 80%
          if (window.scrollTop >= (document.height - window.height)*0.8){
            // отмечаем то, что процесс находится в обработке
            processing = true;
            // отправляем и обрабатываем запрос
            $.get('data.txt', function(data){
              // вставляем контент в контейнер
              $('#container').append(data);
              // отмечаем, что процесс получения данных завершился
              processing = false;
            });
          }
        });
      });
      </script>
      
      Для демонстрации можно создать файл data.txt со следующим содержимым:
      <div class="content">Информация :)</div>
      
      Ну и добавить стиль CSS в вышеприведённый документ:
      <style>
      .content {
        min-height: 1280px;
      }
      </style>
      
      1. Евгений # 0
        Огромное спасибо!!!

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