Czym jest AJAX AJAX wprowadzenie Beata Pańczyk na podstawie: 1. Lis Marcin, Ajax, Helion, 2007 2. Hadlock Kris, Ajax dla twórców aplikacji internetowych, Helion, 2007 AJAX (Asynchronous JavaScript and XML) akronim: A - "asynchroniczny", JA - "JavaScript", X - "XML" pozwala na wysyłanie Ŝądań HTTP do serwera bez odświeŝania okna przeglądarki (asynchronicznie) obiekt XMLHttpRequest (XHR) najwaŝniejszy składnik AJAX 1999 Microsoft udostępnił po raz pierwszy obiekt XHR w IE5 (jako obiekt ActiveX dostępny przez JavaScript i VBScript) obecnie XHR jest obsługiwany przez Mozilla, Firefox, Safari, Opera, Netscape (jako obiekt JavaScript) i IE7 (jako obiekt ActiveX) 2 Niezbędne narzędzia edytor tekstowy (np. ked) przeglądarka WWW (min. IE 5.0, Firefox 1.0, Netscape 7.0, Opera 7.6, Safari dla Apple 1.2) serwer WWW PHP Obiekt XMLHttpRequest (XHR) serce AJAX-a pozwala na: pobieranie przez stronę WWW danych z serwera (za pomocą metody GET) wysyłanie do serwera (za pomocą metody POST) Ŝądania przetwarzanego w tle eliminuje potrzebę oczekiwania po kaŝdym Ŝądaniu na przysłanie przez serwer nowej strony i pozwala uŝytkownikom kontynuować interakcję ze stroną WWW (podczas gdy Ŝądanie jest przetwarzane w tle) metody GET i POST obiektu XHR działają jak w standardowym Ŝądaniu HTTP; najczęściej stosowanymi formatami odpowiedzi są XML, JSON (JavaScript Object Notation) 3 4 Standardowy XHR najprostsza forma modelu Ŝądanie-odpowiedź w AJAX obiekt XHR Ŝąda metodą GET statycznego pliku XML, JSON lub tekstowego znajdującego się w tej samej domenie plik zostaje wysłany przez serwer do klienta, gdzie dane zostają przetworzone przez kod po stronie klienta JavaScript śądanie HTTP klient (X)HTML/CSS Silnik AJAX XML/JSON serwer (X)HTML metoda GET 5 XHR z obsługą baz danych Aktualizowanie BD na podstawie interakcji z uŝytkownikiem bez potrzeby odświeŝania okna przeglądarki pełna kontrola nad BD poprzez XHR JavaScript śądanie HTTP metoda POST Instrukcja do BD klient (X)HTML/CSS Silnik AJAX Baza danych serwer (X)HTML XML/JSON Silnik po stronie serwera Odpowiedź BD 6 1
Tworzenie obiektu XHR var XMLHttpRequestObject = false; if (window.xmlhttprequest) { // przeglądarki poza IE XMLHttpRequestObject = new XMLHttpRequest(); else if(window.activexobject) { // IE XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); if(xmlhttprequestobject) document.write("obiekt XMLHttpRequest został utworzony."); else document.write("obiekt XMLHttpRequest nie został utworzony."); </script> 7 Wynik działania skryptu 8 Właściwości obiektu XHR readystate kod określający status Ŝądania responsetext odpowiedź serwera w postaci tekstowej responsexml - odpowiedź serwera w postaci XML status kod odpowiedzi serwera StatusText kod odpowiedzi serwera w postaci tekstowej 9 Właściwości obiektu XHR var XMLHttpRequestObject = false; if(window.xmlhttprequest){ XMLHttpRequestObject = new XMLHttpRequest(); else if(window.activexobject){ XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); if(xmlhttprequestobject){ for(indeks in XMLHttpRequestObject){ try { document.write(indeks +" = " + XMLHttpRequestObject[indeks] + "<br />"); catch(err) { document.write(indeks + "= \"brak odczytu\"<br />"); </script> 10 </html> Właściwości XHR w FF 11 Metody obiektu XHR abort - przerywa Ŝądanie HTTP getallresponseheaders pobiera nagłówki HTTP w postaci ciągu znaków getresponseheader pobiera wybrany nagłówek HTTP open inicjalizuje Ŝądanie HTTP send wysyła Ŝądanie HTTP do serwera setrequestheader ustawia wybrany nagłówek HTTP overridemimetype nadpisuje nagłówek MIME zwrócony przez serwer 12 2
Wysyłanie Ŝądania do serwera open(metoda_transmisji, url, async, uzytkownik, hasło) inicjalizacja Ŝądania metoda_transmisji GET, POST url adres pliku/skryptu na serwerze async czy transmisja ma być asynchroniczna (true - domyślnie) uŝytkownik, hasło nazwa uŝytkownika i hasło o ile dostęp do serwera wymaga autoryzacji np. open("get", "http://domena.pl/dane.txt"); send(null) - wysłanie Ŝądania 13 Przesyłanie danych między przeglądarką a serwerem odebranie danych realizowane przez własną funkcję z przypisaną jej właściwością onreadystatechange obiektu XMLHttpRequest funkcja obsługi zdarzenia onreadystatechange powstającego przy zmianie stanu obiektu XHR najczęściej stosuje się funkcję anonimową (bez nazwy) postaci: { //tresc funkcji 14 Wartość readystate 0 1 2 3 4 Zmiany stanu obiektu XHR właściwość readystate Załadowany Interaktywny Gotowy Nazwa Niezainicjalizowany Wczytywany Definicja Nie została wywołana metoda open Dane obiektu w trakcie ładowania Obiekt załadowany (wywołana metoda send, ale odpowiedź serwera nie jest jeszcze dostępna) Część danych odebrana i moŝe zostać odczytana Operacja zakończona obiekt został całkowicie zainicjalizowany 15 Kody stanu i nagłówki HTTP Stan Ŝądania jest równowaŝny stanowi HTTP pliku, który został zaŝądany Kody stanu HTTP reprezentują odpowiedź serwera zaleŝną od statusu Ŝądanego pliku Dla Ŝądań HTTP i XHR dostępnych jest pięć kodów stanu: Informacyjny: 1xx Powodzenie: 2xx Przekierowanie: 3xx Błąd klienta: 4xx Błąd serwera: 5xx Właściwość status pozwala na odczytanie kodu odpowiedzi zwróconej przez serwer w rezultacie zapytania 16 Wybrane kody odpowiedzi serwera HTTP Kod 200 202 400 403 404 500 Nieprawidłowe Ŝądanie Dostęp zabroniony Znaczenie śądanie zakończone sukcesem śądanie zaakceptowane do przetwarzania asynchronicznego Brak Ŝądanego dokumentu (pliku) Wewnętrzny błąd serwera 17 Zmiana stanu obiektu (1) //utworzenie obiektu XMLHttpRequest { if (XMLHttpRequestObject) { var calls = 0; var div = document.getelementbyid("div1"); div.innerhtml = ""; XMLHttpRequestObject.open("GET", "http://localhost/dane.txt"); { calls++; var tekst = "Wywołanie nr " + calls + "<br />"; tekst += "readystate = " + XMLHttpRequestObject.readyState + "<br />"; if (XMLHttpRequestObject.readyState!= 1) tekst += "status = " + XMLHttpRequestObject.status + "<br />"; else tekst += "status = niedostępny<br />"; tekst += "<br />"; div.innerhtml = div.innerhtml + tekst; </script> 18 3
Zmiana stanu obiektu (2) <input type="button" value="kliknij tu" onclick="pobierzdane();" /> </html> 19 Transmisja danych z serwera (1)... var div = document.getelementbyid("div1"); XMLHttpRequestObject.open("GET", "http://localhost/ajax/dane.txt"); div.innerhtml = XMLHttpRequestObject.responseText; </script> </head> <input type="button" value="kliknij tu" onclick="pobierzdane();" /> Ten tekst zostanie zmieniony. </html> 20 Transmisja danych z serwera (2) 21 Odbieranie danych przez zwykłą funkcję... function przetwarzajdane() var div = document.getelementbyid("div1"); div.innerhtml = XMLHttpRequestObject.responseText; XMLHttpRequestObject.open("GET", "http://localhost/ajax/dane.txt"); XMLHttpRequestObject.onreadystatechange = przetwarzajdane; </script> </head> <!-- tu bez zmian --> </html> 22 Pobieranie danych z róŝnych plików (1) <input type="button" value="pierwszy tekst" onclick="pobierzdane(1);" /> <input type="button" value="drugi tekst" onclick="pobierzdane(2);" /> <input type="button" value="trzeci tekst" onclick="pobierzdane(3);" /> Ten tekst zostanie zmieniony. 23 Pobieranie danych z róŝnych plików (2) function pobierzdane(tekstid) { if(xmlhttprequestobject) { switch(tekstid) { case 1: XMLHttpRequestObject.open("GET", "http://localhost/dane1.txt");break; case 2: XMLHttpRequestObject.open("GET", "http://localhost/dane2.txt");break; case 3: XMLHttpRequestObject.open("GET", "http://localhost/dane3.txt");break; default: return; { var div = document.getelementbyid("div1"); div.innerhtml = XMLHttpRequestObject.responseText; 24 4
Lista rozwijana i teksty (1) <select id="lista" size="1" onchange="pobierzdane();"> <option value="0">wybierz opcję <option value="1">pierwszy tekst <option value="2">drugi tekst <option value="3">trzeci tekst </select> Ten tekst zostanie zmieniony. Lista rozwijana i teksty (2) var lista = document.getelementbyid('lista'); var tekstid = parseint(lista[lista.selectedindex].value); switch(tekstid) { case 1:XMLHttpRequestObject.open("GET", "http://localhost/dane1.txt");break; case 2:XMLHttpRequestObject.open("GET", "http://localhost/dane2.txt");break; case 3:XMLHttpRequestObject.open("GET", "http://localhost/dane3.txt");break; default: return; { var div = document.getelementbyid("div1"); div.innerhtml = XMLHttpRequestObject.responseText; 25 26 Wyświetlanie obrazu (1) <input type="button" value="kliknij tu" onclick="pobierzdane();" /> <br /><br /> Tutaj pojawi się obraz. 27 Wyświetlanie obrazu (2) { if(xmlhttprequestobject){ XMLHttpRequestObject.open("GET", "http://localhost/obraz.txt"); var div = document.getelementbyid("div1"); var obraz = XMLHttpRequestObject.responseText; //pobranie //zawartości pliku obraz.txt var tag = "<img src=\"" + obraz + "\" alt=\"opis obrazu\">"; div.innerhtml = tag; 28 Dynamiczne zmiany na stronie (1) <input type="button" value="menu 1" onmouseover="pobierzdane('b1', 'div1')" /> <input type="button" value="menu 2" onmouseover="pobierzdane('b2', 'div1')" /> <input type="button" value="menu 3" onmouseover="pobierzdane('b3', 'div1')" /> <br /><br /> 29 Dynamiczne zmiany na stronie (2) function pobierzdane(id, el) { if (XMLHttpRequestObject) { switch(id) { case "b1":xmlhttprequestobject.open("get", "http://localhost/dane1.txt");break; case "b2":xmlhttprequestobject.open("get", "http://localhost/dane2.txt");break; case "b3":xmlhttprequestobject.open("get", "http://localhost/dane3.txt");break; default: return; var div = document.getelementbyid(el); var tekst = XMLHttpRequestObject.responseText; div.innerhtml = tekst; 30 5
Dynamiczne zmiany obrazu (1) <input type="button" value="menu 1" onmouseover="pobierzdane('b1', 'imgdiv1')" /> <input type="button" value="menu 2" onmouseover="pobierzdane('b2', 'imgdiv1')" /> <input type="button" value="menu 3" onmouseover="pobierzdane('b3', 'imgdiv1')" /> <br /><br /> <div id="imgdiv1"> 31 Dynamiczne zmiany obrazu (2) function pobierzdane(id, el) switch(id) { case "b1": XMLHttpRequestObject.open("GET", "http://localhost/obraz1.txt");break; case "b2": XMLHttpRequestObject.open("GET", "http://localhost/obraz2.txt");break; case "b3": XMLHttpRequestObject.open("GET", "http://localhost/obraz3.txt");break; default: return; var div = document.getelementbyid(el); var obraz = XMLHttpRequestObject.responseText; var tag = "<img src=\"" + obraz + "\" alt=\"obraz\">"; div.innerhtml = tag; 32 Wykonanie instrukcji pobranej z serwera (1) <input type="button" value="kliknij mnie!" onclick="pobierzdane();" /> Plik skrypt.js: Wykonanie instrukcji pobranej z serwera (2) { if(xmlhttprequestobject){ XMLHttpRequestObject.open("GET", "skrypt.js" ); { if (XMLHttpRequestObject.readyState == 4 && var kod = XMLHttpRequestObject.responseText; eval(kod); alert("funkcja pobrana z serwera."); 33 34 AJAX i PHP <input type="button" value="kliknij mnie!" onclick="pobierzdane('d1');" /> <div id="d1">ten tekst zostanie zmieniony Skrypt PHP na serwerze http://localhost/ajax/skrypt.php <?php $data=date("y-m-d"); echo "Dzisiaj jest: $data <br />"; echo "Data wygenerowana przez skrypt PHP"; AJAX i PHP //utworzenie obiektu XMLHttpRequestObject... function pobierzdane(dest) { if(xmlhttprequestobject) { var div=document.getelementbyid(dest); XMLHttpRequestObject.open("GET", "http://localhost/ajax/skrypt.php"); { var kod = XMLHttpRequestObject.responseText; div.innerhtml=xmlhttprequestobject.responsetext; 35 36?> </script> 6
AJAX i PHP 37 Zalety AJAX-a zwiększenie poziomu interaktywności z uŝytkownikiem skrócenie czasu ładowania stron aplikacji - asynchroniczne pobieranie z serwera danych oraz kodu JavaScript i reguł CSS wtedy gdy są potrzebne powszechne wsparcie technologii składowych AJAX przez obecne przeglądarki bez konieczności instalowania wtyczek czy bibliotek runtime (w przeciwieństwie do alternatywnych rozwiązań - aplety Java, Flash) ograniczenie ilości danych przesyłanych z serwera do przeglądarki i przeniesienie części przetwarzania na komputer uŝytkownika (redukcja ruchu w sieci i obciąŝenia serwera aplikacji) coraz więcej wzorców projektowych, bibliotek, szkieletów aplikacji i środowisk IDE wspierających AJAX 38 Wady JavaScript, w którym implementowana jest logika aplikacji po stronie klienta to język skryptowy - nie został zaprojektowany do tworzenia duŝych aplikacji; jest językiem interpretowanym, ze słabą kontrolą typów danych; mechanizmy obiektowe są oparte o prototyp (nie o klasy) konieczność włączenia obsługi JavaScript w przeglądarce (w przypadku IE równieŝ obsługi ActiveX) ewentualne opóźnienia w komunikacji sieciowej - nie powodują wstrzymania działań uŝytkownika, ale sprawiają, Ŝe efekty jego interakcji z aplikacją mogą nie być natychmiastowe brak moŝliwości cofania zdarzeń i przeglądania historii (asynchroniczne przesyłanie danych nie powoduje odświeŝenia strony) trudna implementacja złoŝonych aplikacji AJAX (trudne testowanie i debugowanie aplikacji, co wynika z natury języka JavaScript oraz z podziału logiki aplikacji między klienta i serwer) 39 7