Zajęcia 4
4. Technologia AJAX
4.1. Podstawowe informacje
AJAX to technika wczytywania wczytywania danych we fragmencie strony bez potrzeby odświeżania jej całości. Dane są najczęściej dostarczane w formacie o nazwie JSON.
AJAX wykorzystuje model przetwarzania asynchronicznego. Oznacza to, że użytkownik może wykonywać inne zadania, gdy przeglądarka internetowa oczekuje na wczytanie danych.
Jak to działa?
-
Żądanie - przeglądarka wysyła do serwera WWW żądanie pewnych danych. Żądanie może zawierać informacje wymagane przez serwer; podobnie formularz sieciowy wysyła dane do serwera. W przeglądarkach implementowany jest obiekt o nazwie XMLHttpRequest przeznaczony do obsługi żądań AJAX. Po wysłaniu żądania przeglądarka nie musi czekać na udzielenie odpowiedzi przez serwer.
-
Serwer WWW - udziela odpowiedzi, dostarczając żądane dane (najczęściej w formacie HTML, XML lub JSON). Operacje przeprowadzane na serwerze nie są częścią tego, co określamy mianem AJAX.
-
Odpowiedź - kiedy serwer zakończy udzielanie odpowiedzi na żądanie, przeglądarka wywołuje zdarzenie. Zdarzenie to można wykorzystać do uruchomienia funkcji JS przetwarzającej dane i umieszczającej je na stronie.
Przykład 4.1.1.
/* Żądanie */
let xhr = new XMLHttpRequest(); // utworzenie obiektu XHR
xhr.open('GET', 'data/test.json', true); // przygotowanie żądania
/* W powyższej metodzie pierwszy argument to nazwa metody HTTP, drugi to adres URL strony, która będzie obsługiwać żądanie, trzeci to wartość boolowska, wskazująca, czy żądanie powinno być asynchroniczne*/
xhr.send(null); // wysłanie żądania bez dodatkowych informacji dodatkowych
/* Odpowiedź */
xhr.onload = function() { // wykonanie funkcji anonimowej dla zdarzenia ONLOAD
if (xhr.status === 200) { // jeśli status wynosi 200 to OK
// przetworzenie odpowiedzi
}
}
4.2. Formaty danych
4.2.1. XML
Przykład 4.2.1.1.
<?xml version="1.0" encoding="utf-8" ?>
<events>
<event>
<location>San Francisco, CA</location>
<date>1 maja</date>
<map>img/map-ca.png</map>
</event>
<event>
<location>Austin, TX</location>
<date>15 maja</date>
<map>img/map-tx.png</map>
</event>
<event>
<location>Nowy Jork, NY</location>
<date>30 maja</date>
<map>img/map-ny.png</map>
</event>
</events>
4.2.2. JSON
Przykład 4.2.2.1.
{
"events": [
{
"location": "San Francisco, CA",
"date": "1 maja",
"map": "img/map-ca.png"
},
{
"location": "Austin, TX",
"date": "15 maja",
"map": "img/map-tx.png"
},
{
"location": "Nowy Jork, NY",
"date": "30 maja",
"map": "img/map-ny.png"
}
]
}
Jak przekonwertować obiekt JavaScript na JSON?
JSON.stringify(obiekt);
Jak przetworzyć JSON na obiekt JavaScript?
JSON.parse(daneJSON);
Ćwiczenie 4.2.1.
Przygotuj pliki XML oraz JSON, w których będą znajdowały się informacje o Twoich 5 ulubionych piosenkach. Dla pojedynczej piosenki powinny się tam znaleźć dane takie jak: tytuł, wykonawca, gatunek, album, rok wydania.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_04. Pliki z rozwiązaniem nazwij exercise_421.xml i exercise_421.json.
4.2.3. Wczytywanie HTML
Pobierz archiwum AJAX.
Przykład 4.2.3.1.
var xhr = new XMLHttpRequest(); // Utworzenie obiektu XMLHttpRequest.
xhr.onload = function() { // Po wczytaniu odpowiedzi.
if(xhr.status === 200) { // Jeżeli stan serwera wskazuje, że wszystko jest w porządku.
document.getElementById('content').innerHTML = xhr.responseText; // Uaktualnienie.
}
};
xhr.open('GET', 'data/data.html', true); // Przygotowanie żądania.
xhr.send(null); // Wykonanie żądania.
4.2.4. Wczytywanie XML
Przykład 4.2.4.1.
var xhr = new XMLHttpRequest(); // Utworzenie obiektu XMLHttpRequest.
xhr.onload = function() { // Po wczytaniu odpowiedzi.
if (xhr.status === 200) { // Jeżeli stan serwera wskazuje, że wszystko jest w porządku.
// Ten fragment jest inny, ponieważ przetwarzane są dane XML, a nie HTML.
var response = xhr.responseXML; // Pobranie danych XML z serwera.
var events = response.getElementsByTagName('event'); // Wyszukanie elementów <event>.
for (var i = 0; i < events.length; i++) { // Iteracja przez znalezione elementy.
var container, image, location, city, newline; // Deklaracja zmiennych.
container = document.createElement('div'); // Utworzenie pojemnika <div>.
container.className = 'event'; // Dodanie atrybutu class.
image = document.createElement('img'); // Dodanie obrazu mapy.
image.setAttribute('src', getNodeValue(events[i], 'map'));
image.appendChild(document.createTextNode(getNodeValue(events[i], 'map')));
container.appendChild(image);
location = document.createElement('p'); // Dodanie danych dotyczących lokalizacji.
city = document.createElement('b');
newline = document.createElement('br');
city.appendChild(document.createTextNode(getNodeValue(events[i], 'location')));
location.appendChild(newline);
location.insertBefore(city, newline);
location.appendChild(document.createTextNode(getNodeValue(events[i], 'date')));
container.appendChild(location);
document.getElementById('content').appendChild(container);
}
function getNodeValue(obj, tag) { // Pobranie zawartości z danych XML.
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
// Ostatni fragment jest taki sam jak w przypadku danych HTML, ale żądanie dotyczy pliku XML.
}
};
xhr.open('GET', 'data/data.xml', true); // Przygotowanie żądania.
xhr.send(null); // Wykonanie żądania.
4.2.5. Wczytywanie danych JSON
var xhr = new XMLHttpRequest(); // Utworzenie obiektu XMLHttpRequest.
xhr.onload = function() { // Po zmianie stanu.
if(xhr.status === 200) { // Jeżeli stan serwera wskazuje, że wszystko jest w porządku.
responseObject = JSON.parse(xhr.responseText);
// Utworzenie ciągu tekstowego wraz z nową zawartością (można użyć także operacji opartych na modelu DOM).
var newContent = '';
for (var i = 0; i < responseObject.events.length; i++) { // Iteracja przez obiekt.
newContent += '<div class="event">';
newContent += '<img src="' + responseObject.events[i].map + '" ';
newContent += 'alt="' + responseObject.events[i].location + '" />';
newContent += '<p><b>' + responseObject.events[i].location + '</b><br>';
newContent += responseObject.events[i].date + '</p>';
newContent += '</div>';
}
// Uaktualnienie strony nową zawartością.
document.getElementById('content').innerHTML = newContent;
}
};
xhr.open('GET', 'data/data.json', true); // Przygotowanie żądania.
xhr.send(null); // Wykonanie żądania.
Ćwiczenie 4.2.2.
Przygotuj stronę, na której zostaną wyświetlone informacje o Twoich 5 ulubionych piosenkach. Na stronie powinno być 5 przycisków - każdy z tytułem piosenki. Po kliknięciu na przycisk ten staje się nieaktywny a na stronie pojawiają się szczegóły pobrane z pliku (XML lub JSON). Po kliknięciu innego przycisku ten stary jest aktywny a obecnie kliknięty nieaktywny. W tym momencie dane są aktualizowane na stronie bez odświeżania całości. Napisz dwa skrypty języka JavaScript, które będą wczytywać dane, które przygotowałeś(łaś) w poprzednim zadaniu. Pierwszy wczytuje dane XML a drugi dane JSON.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_04. Skrypty z rozwiązaniem nazwij exercise_422XML.js oraz exercise_422JSON.js.
4.3. Praca z danymi pochodzącymi z innych serwerów
AJAX działa doskonale w przypadku danych pochodzących z Twojego serwera, ale ze względów bezpieczeństwa przeglądarki internetowe nie wczytują odpowiedzi AJAX z innych domen (odpowiedzi będących wynikiem tzw. żądań typu cross-domain). Dostępne są trzy najczęściej stosowane rozwiązania tego problemu:
- plik proxy w serwerze WWW - utworzenie we własnym serwerze pliku przeznaczonego na dane pochodzące ze zdalnego serwera. Strony w Twojej witrynie będą żądały danych ze wspomnianego pliku w serwerze, który z kolei pobierze odpowiednie dane z serwera zdalnego. Takie rozwiązanie nosi nazwę proxy, ponieważ działa w imieniu innej strony;
- Cross-Origin-Resource-Sharing - w trakcie komunikacji przeglądarki internetowej i serwera WWW informacje między nimi są przekazywane za pomocą nagłówków HTTP. CORS (ang. Cross-Origin Resource Sharing) oznacza umieszczanie w nagłówkach HTTP dodatkowych informacji, które wskazują przeglądarce i serwerowi WWW sposób prowadzenia komunikacji;
- JSONP - obejmuje dodanie na stronie elementu <script> odpowiedzialnego za wczytanie danych JSON z innego serwera. Takie rozwiązanie działa, ponieważ nie istnieją ograniczenia dotyczące źródła pochodzenia skryptu w elemencie <script>. Skrypt zawiera wywołanie funkcji, a dane w formacie JSON dostarczane są jako argument funkcji. Wywołana funkcja jest zdefiniowana na stronie żądającej danych i używana jest do ich przetworzenia oraz wyświetlenia.
Zadania domowe
Zadanie 1.
Przygotuj plik o nazwie data.json i wypełnij go danymi na temat swoich ulubionych filmów. W pliku powinno być 5 obiektów, każdy powinien zawierać informacje takie jak: tytuł filmu, gatunek, reżyser, rok nakręcenia, krótki opis fabuły.
Przygotuj kod HTML oraz JavaScript, który wyświetli te dane na stronie w następujący sposób:
- jest 5 przycisków, każdy ma jako treść tytuł filmu (pobrany z pliku JSON);
- po kliknięciu danego przycisku pojawiają się wszystkie szczegóły wybranego pliku (te, które są w data.json) - kliknięty przycisk powinien stać się nieaktywny;
- po kliknięciu innego przycisku dane na temat filmu są aktualizowane bez odświeżania całej strony a poprzedni przycisk staje się znów aktywny - nieaktywny za to staje się aktualnie kliknięty.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_04. Skrypt z rozwiązaniem nazwij homework_task_01.js, kod strony homework_task_01.html oraz dane - data.json.
Zadanie 2.
Wymień w punktach (jako stronę HTML), jakie Twoim zdaniem są wady i zalety korzystania z formatów danych (HTML, XML, JSON), w których otrzymujemy odpowiedź na żądanie przeglądarki.
Rozwiązanie wyślij na repozytorium Githuba do katalogu Lesson_04. Plik z rozwiązaniem nazwij homework_task_02.html.
Źródła
- Duckett Jon, JavaScript and JQuery: Interactive Front-End Web Development, przeł. Robert Górczyński, Helion, 2015, ISBN 978-83-283-0126-9.