Открыть меню    

AJAX основы

ajaxПробежимся по статьям об AJAX на сайте dnzl.ru
(некоторые статьи морально устарели и содержат неточности перевода):

  1. Парсим JSON: «Преобразуем строку формата JSON в объект и наоборот»
    /view_post.php?id=350.
    Рассматриваются нативные методы JSON.parse() и JSON.stringify( ), а также метод jQuery $.parseJSON.
  2. «JSON для начинающих, с использованием javascript и jQuery»
    /view_post.php?id=289
    Основные моменты статьи:
    Массив, как и числа, в формате JSON не заключаются в кавычки.
    Рассматривается метод библиотеки jQuery $.getJSON.
  3. «Знакомство с укороченными Ajax методами jQuery»
    /view_post.php?id=345
    Рассматривается:
    Укороченные методы load(), $.post(), и $.get(). Приведены примеры на codepen.
  4. «Ajax запрос методом GET с примерами»
    /view_post.php?id=283
    Рассматривается метод jQuery $.get(). Приведен пример использования.
  5. «Ajax запрос методом POST, пример с использованием json_encode»
    /view_post.php?id=285
    Рассматриваются методы PHP json_decode() и json_encode().
    Приведен пример метода jQuery $.post().
    Рассмотрена сериализация формы $(this).serialize().
  6. «Функция jQuerys $.ajax()»
    /view_post.php?id=344
    Рассматривается:
    Метод jQuery $.ajax() с кратким описанием всех параметров метода.
    Приведен пример создание запроса JSONP с целью получения информации от сервиса Joind.in.
  7. «Метод jQuery getJSON»
    /view_post.php?id=284
    Рассматривается пример использования метода jQuery $.getJSON()

Другие статьи:

  1. Динамическая (ajax) загрузка контента с jcarousel
    (/view_post.php?id=304)
  2. Ajax слайдер (jQuery и PHP)
    /view_post.php?id=273
  3. PHP и AJAX для начинающих на простом примере
    /view_post.php?id=271
    Получаем адрес студента при помощи метода jQuery $.ajax, по порядковому номеру студента и его имени.
  4. Создаем прокручиваемый блок с динамическим контентом на AJAX
    /view_post.php?id=274
  5. Ajax добавить и удалить данные из базы данных, используя jQuery и PHP
    /view_post.php?id=272

Инструменты:

fiddler

Изучение технологий Ajax: https://vk.com/wall-54530371_60540

Заголовки ответа PHP:

PHP

header('Content-Type: text/javascript; charset=utf-8');
header('Content-Type: text/html; charset=utf-8');

jQuery load

http://dnzlru/demo/ajax/jquery_load.html

HTML

<div id="targetDiv"></div>
<button class="load">Загрузить</button>
<button class="clear">Очистить</button>

jQuery or Javascript

<script type="text/javascript">
$(function() {
    $(".load").click(function() {
        $("#targetDiv").load("testLoad.htm");
    });
    $(".clear").click(function() {
        $("#targetDiv").empty();
    });
});
</script>

Загружаем только нужные элементы

Загружаем только нужные элементы. Для этого после url делаем пробел и перечисляем через запятую необходимые элементы (селекторы): http://dnzlru/demo/ajax/jquery_load_selector.html

jQuery or Javascript

$(function() {
    $(".load").click(function() {
        $("#targetDiv").load("testLoad.htm  h2,p:last", function(){ alert("Первый пошел"); });
    });
    $(".clear").click(function() {
        $("#targetDiv").empty();
    });
});

$.load, получаем ответ от сервера сформированный на основе отправленных ему данных

jquery_load_data.html

jQuery or Javascript

$(function() {
    $(".load").click(function() {
        $("#target").load("testLoad.php", {
                name: "Константин",
                age: "33"
            },
            function(responseText, textStatus, XMLHttpRequest) {
                $("#targetInfo").html('textStatus = ' + textStatus +
                    '<br/>Свойство readyState объекта XMLHttpRequest: ' + XMLHttpRequest.readyState +
                    '<br/>Свойство status объекта XMLHttpRequest: ' + XMLHttpRequest.status);
            });
    });
    $(".clear").click(function() {
        $("#target, #targetInfo").empty();
    });
});

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  if($_POST) {
    print 'Имя: ' . $_POST['name'] . ', возраст: ' . $_POST['age'] . ', время: ' . date('H:i:s', time());
  }
}

$.get

Посылаем данные на сервер и вставляем ответ в нужный нам элемент

jquery_get.html

jQuery or Javascript

    $(function() {
        $(".load").click(function() {
            $.get("testGet.php", {
                    name: "Константин",
                    age: "35"
                },
                function(data) {
                    $("div").text(data);
                });
        });
        $(".clear").click(function() {
            $("div").empty();
        });
    });

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  if($_GET) {
    print 'Имя: ' . $_GET['name'] . ', возраст: ' . $_GET['age'] . ', время: ' . date('H:i:s', time());
  }
}

Метод jQuery $.getJSON

Загружаем JSON данные при помощи метода jQuery $.getJSON

jQuery or Javascript

$(".getJSON").click(function() {
    $.getJSON("testGetJSON.php", function(data, textStatus, jqXHR) {
        var items = [];
        $.each(data, function(i, item) {
            items.push(item.name + ': ' + item.phone);
        });
        $("div#target").html(items.join('
')); }); });

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  print '[{"name":"Боб","phone":"565-76-17"},
          {"name":"Елена","phone":"511-77-77"},
          {"name":"Адам","phone":"523-45-77"},
          {"name":"Крис","phone":"578-66-99"}]';
}

Загружаем JSON данные при помощи метода jQuery $.getJSON с другого домена

jQuery or Javascript

$(".getJSONP").click(function() {
    $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=nature&tagmode;=any&format;=json&jsoncallback;=?",
        function(data) {
            $.each(data.items, function(i, item) {
                $("").attr("src", item.media.m)
                    .attr("title", item.title)
                    .appendTo("div#targetImg");
                if (i == 2) return false;
            });
        });
});

jquery_get_json.html

Метод jQuery $.post

Отправляем данные на сервер; ответ вставляем в определенный элемент.

jQuery or Javascript

        $(".load").click(function() {
            $.post("testPost.php", {
                    name: "Константин",
                    age: "33"
                },
                function(data) {
                    $("div#target").text(data);
                });
        });

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  if($_POST) {
    print 'Имя: ' . $_POST['name'] . ', возраст: ' . $_POST['age'] . ', время: ' . date('H:i:s', time());
  }
}

jquery_post.html

Методы jQuery $.ajax() и $.ajaxSetup()

  1. Отправляем данные на сервер
  2. Выполняем действия перед отправкой на сервер
  3. Контролируем max время ожидания ответа
  4. В случае успеха выполняем какое-либо действие

jquery_ajax.html

jQuery or Javascript

$(".load").click(function() {
    $.ajax("testAjax.php", {
        type: "POST",
        data: $('form').serialize(),
        timeout: 5000,
        beforeSend: function() {
            $("#target").text("Загрузка...");
        },
        success: function(data, textStatus, jqXHR) {
            $("#target").html(data + '<br />Статус ответа: ' + textStatus +
                '<br />Код ответа сервера: ' + jqXHR.status);
        },
        error: function(jqXHR, textStatus) {
            $("#target").html( textStatus +
                '<br />Код ответа сервера: ' + jqXHR.status);
        }
    });
});

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
  for($i=0;$i<2;$i++){
    sleep(1);
  }
  if($_POST){
    print '<h3>Ответ сервера</h3><p>Время: '.date("H:i:s", time()).'</p>
    <p>Имя: ' . $_POST['name'] . ', возраст: ' . $_POST['age'].'</p>';
  }
}

Ajax-запросы идентичны, но различие в отправляемых данных

ajax_same.html

Настройки используемые в $.ajaxSetup() будут использоваться для всех ajax-запросов страницы.

jQuery or Javascript

$(function() {
    $.ajaxSetup({
        url: "testAjaxSetup.php",
        type: "POST",
        timeout: 3000,
        beforeSend: function() {
            $("#target").empty();
            $("#result").text("Загрузка...");
        },
        success: function(data) {
            $("div:last").html(data);
            $("#result").text("Готово!");
        },
        error: function(jqXHR, textStatus) {
            $("#result").html('Статус ответа: ' + textStatus +
                '<br />Код ответа сервера: ' + jqXHR.status);
        }
    });
    $("button:eq(0)").click(function() {
        $.ajax({
            data: "q=1&er;=none"
        });
    });
    $("button:eq(1)").click(function() {
        $.ajax({
            data: "q=3&er;=yes"
        });
    });
});

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
    if($_POST['er'] == "yes") { for($i=0;$i<5;$i++) sleep(1); }
    if($_POST){
    print   '<h3>Ответ сервера</h3>
            <p>В '.date("H:i:s d-m-Y", time()).
            ' получены данные:<br />
            <strong>q = ' . $_POST['q'] . ',
            er = ' . $_POST['er'] .
            '</strong></p>';
    }
}

Локальные и глобальные события при AJAX-запросе

jquery_event_ajax.html

new Date().getTime() - время прошедшее с 1 января 1970 года, в мс.

jQuery or Javascript

$(function() {
    var start = new Date().getTime();
    // глобальные настройки
    $.ajaxSetup({
        url: "testEvents.php",
        type: "POST",
        timeout: 4000,
        beforeSend: function() {
            $("#result").append(new Date().getTime() - start + ' мс ==> beforeSend');
        },
        success: function() {
            $("#result").append(new Date().getTime() - start + ' мс ==> success');
        },
        error: function() {
            $("#result").append(new Date().getTime() - start + ' мс ==> error');
        },
        complete: function() {
            $("#result").append(new Date().getTime() - start + ' мс ==> complete');
        }
    });
    // успешный запрос
    $("#well").click(function() {
        $("div").empty();
        start = new Date().getTime();
        $.ajax({
            data: "er=none"
        });
    });
    // ошибочный запрос
    $("#bad").click(function() {
        $("div").empty();
        start = new Date().getTime();
        $.ajax({
            data: "er=yes"
        });
    });
    $("#clear").click(function() {
        $("div").empty();
    });
    // обработка глобальных событий
    $(document).ajaxStart(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxStart');
    }).ajaxSend(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxSend');
    }).ajaxSuccess(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxSuccess');
    }).ajaxError(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxError');
    }).ajaxComplete(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxComplete');
    }).ajaxStop(function() {
        $("#result2").append(new Date().getTime() - start + ' мс ==> ajaxStop');
    });
});

PHP

header('Content-Type: text/html; charset=utf-8');
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
    if($_POST['er'] == "yes") {
        sleep(5);
    }
}

Формируем запрос руками

GET и POST запросы

var params = 'name=' + encodeURIComponent(name) +
  '&surname;=' + encodeURIComponent(surname);

Чтоб избежать неожиданных запросов к серверу, вам следует вызывать encodeURIComponent для любых вводимых пользователем параметров, используемых как часть URI.
developer.mozilla.org: encodeURIComponent

Кросс-доменные запросы

CORS

learn.javascript.ru: xhr-crossdomain#cors

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

GET /request
Host:anywhere.com
Origin:http://blalala.com
...

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

Если сервер разрешает кросс-доменный запрос с этого домена – он должен добавить к ответу заголовок Access-Control-Allow-Origin, содержащий домен запроса (в данном случае «blalala.com») или звёздочку *.

Вероятный ответ сервера:

HTTP/1.1 200 OK
Content-Type:text/html; charset=UTF-8
Access-Control-Allow-Origin: http://javascript.ru

Запросы от имени пользователя

По умолчанию браузер не передаёт с запросом куки и авторизующие заголовки.

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

Полезные статьи

Основы XMLHttpRequest https://learn.javascript.ru/ajax-xmlhttprequest

AJAX. Основы.easywebscripts.net/ajax/ajax_fundamentals.php

При запросе с withCredentials сервер должен вернуть уже не один, а два заголовка:

    Access-Control-Allow-Origin: домен
    Access-Control-Allow-Credentials: true

p.s. Функция sleep Откладывает исполнение программы на число секунд, заданное параметром seconds. php.net/manual/ru/function.sleep.php

Комментарии к статье