Один из краеугольных камней современных веб-приложений находится за сценой - ассинхронный обмен данными между сервером и Javascript'ом, работающим в браузере. Хотя Ajax это стандарт для XML, в реальности многие приложения отправляют данные в формате JSON. В большинстве случаев это удобнее, чем использовать XML.
Чтобы сделать этот пример проще, я создал JSON файл на сервере, который мы будем запрашивать. В реальной ситуации сервер бы сгенерировал такой 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 сниппет.
<h1 id="title"></h1>
<hr>
<div id="text"></div>
<script src="ajax.js"></script>
JavaScript код выглядит вот так:
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.