Один из краеугольных камней современных веб-приложений находится за сценой - ассинхронный обмен данными между сервером и Javascript'ом, работающим в браузере. Хотя Ajax это стандарт для XML, в реальности многие приложения отправляют данные в формате JSON. В большинстве случаев это удобнее, чем использовать XML.

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

examples/js/data.json

{
   "title" : "Code Maven",
   "description" : "Coding is fun!",
   "articles" : [
       {
          "title" : "Handling user events in JavaScript",
          "url"   : "http://code-maven.com/handling-events-in-javascript"
       },
       {
          "title" : "On-load counter with JavaScript and local storage",
          "url"   : "http://code-maven.com/on-load-counter-with-javascript-and-local-storage"
       }
   ]
}

У нас есть HTML страница с элементом h1, который мы собираемся заполнить значением ключа "title", также есть элемент div, для которого мы соберем HTML сниппет.

examples/js/ajax.html

<h1 id="title"></h1>
<hr>
<div id="text"></div>

<script src="ajax.js"></script>
Try!

JavaScript код выглядит вот так:

examples/js/ajax.js

function ajax_get(url, callback) {
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            console.log('responseText:' + xmlhttp.responseText);
            try {
                var data = JSON.parse(xmlhttp.responseText);
            } catch(err) {
                console.log(err.message + " in " + xmlhttp.responseText);
                return;
            }
            callback(data);
        }
    };

    xmlhttp.open("GET", url, true);
    xmlhttp.send();
}

ajax_get('/try/examples/js/data.json', function(data) {
    document.getElementById("title").innerHTML = data["title"];

    var html = "<h2>" + data["title"] + "</h2>";
    html += "<h3>" + data["description"] + "</h3>";
    html += "<ul>";
       for (var i=0; i < data["articles"].length; i++) {
           html += '<li><a href="' + data["articles"][i]["url"] + '">' + data["articles"][i]["title"] + "</a></li>";
       }
    html += "</ul>";
    document.getElementById("text").innerHTML = html;
});


Весь код, относящийся к отправке асинхронного запроса, был помещен в функцию ajax_get. Эта функция принимает два параметра. Первый - URL, который мы запрашиваем. Это может быть URL примерно такой http://somesite.com/some/page, или он может быть без имени хоста, например /some/page, если мы хотим отправить запрос на тот же сервер, с которого получили наш JavaScript. Так же мы можем отправлять параметры, добавляя их после URL. Примерно так: http://somesite.com/some/page?fname=Foo&lname=Bar.

Второй параметр - это функция, которая будет вызвана, когда от сервера придет ответ.

В нашем примере мы ожидаем, что ответом будет корректный JSON.

Пройдемся по функции: сначала мы создали объект XMLHttpRequest(). Затем мы присвоили атрибуту onreadystatechange вызов функции. Функция будет вызвана, когда прийдет корректный ответ. Затем мы вызываем open, здесь мы используем url, и в итоге отправляем запрос функцией send. Здесь вызов нашей функции завершается и приложение может дальше заниматься своими делами, пока...

Пока сервер не ответит. В этот момент будет вызвана функция, связанная с onreadystatechange. Внутри функции мы проверяем, что запрос действительно был успешным, и затем смотрим на атрибут responseText, который будет содержать ответ в виде текста. В этом примере мы отправляем его в консоль для того, чтобы видеть, что мы получили. Дальше здесь есть блок try-catch, оборачивающий вызов JSON.parse. Это может сэкономить немало времени, если сервер возвратит строку, которая не будет правильным JSON. (Например, с лишними или пропущенными запятыми). Затем идет интересная часть. Мы вызываем функцию callback(data), которую ajax_get получила вторым параметром, и передаем туда данные (уже в виде JavaScript объекта).

Это что касается реализации функции ajax_get, но как нам ее использовать?

ajax_get('/try/examples/js/data.json', function(data) {
    document.getElementById("title").innerHTML = data["title"];
});

Мы вызываем функцию ajax_get, передавая ей url (относительный к текущему серверу), и мы также передаем функцию, которая принимает единственную переменную. Это коллбек-функция и ее параметр будет содержать данные, полученные от сервера. Затем мы можем получить доступ к атрибутам объекта JavaScript также, как и в случае любого другого Javascript объекта, и устанавливаем атрибут innerHTML элемента с id "title".

Вот так мы можем использовать ajax-запрос.

Сборка HTML

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