AJAX основы
Пробежимся по статьям об AJAX на сайте dnzl.ru
 (некоторые статьи морально устарели и содержат неточности перевода):
- Парсим JSON: «Преобразуем строку формата JSON в объект и наоборот»
/view_post.php?id=350.
Рассматриваются нативные методыJSON.parse()иJSON.stringify( ), а также метод jQuery$.parseJSON. - «JSON для начинающих, с использованием javascript и jQuery»
/view_post.php?id=289
Основные моменты статьи:Массив, как и числа, в формате JSON не заключаются в кавычки.Рассматривается метод библиотекиjQuery $.getJSON. - «Знакомство с укороченными Ajax методами jQuery»
/view_post.php?id=345
Рассматривается:Укороченные методыload(),$.post(), и$.get(). Приведены примеры на codepen. - «Ajax запрос методом GET с примерами»
/view_post.php?id=283Рассматривается метод jQuery$.get(). Приведен пример использования. - «Ajax запрос методом POST, пример с использованием json_encode»
/view_post.php?id=285
Рассматриваются методы PHPjson_decode()иjson_encode().Приведен пример метода jQuery$.post().Рассмотрена сериализация формы$(this).serialize(). - «Функция jQuerys $.ajax()»
/view_post.php?id=344Рассматривается:Метод jQuery$.ajax()с кратким описанием всех параметров метода.Приведен пример создание запроса JSONP с целью получения информации от сервиса Joind.in. - «Метод jQuery getJSON»
/view_post.php?id=284
Рассматривается пример использования метода jQuery$.getJSON() 
Другие статьи:
- Динамическая (ajax) загрузка контента с jcarousel
(/view_post.php?id=304) - Ajax слайдер (jQuery и PHP)
/view_post.php?id=273 - PHP и AJAX для начинающих на простом примере
/view_post.php?id=271Получаем адрес студента при помощи метода jQuery$.ajax, по порядковому номеру студента и его имени. - Создаем прокручиваемый блок с динамическим контентом на AJAX
/view_post.php?id=274 - 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 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 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 $.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 $.ajax() и $.ajaxSetup()
- Отправляем данные на сервер
 - Выполняем действия перед отправкой на сервер
 - Контролируем max время ожидания ответа
 - В случае успеха выполняем какое-либо действие
 
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-запросы идентичны, но различие в отправляемых данных
Настройки используемые в $.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-запросе
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

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