AJAX – Tutorial

Transcription

AJAX – Tutorial
AJAX – Tutorial
Das Wort Ajax ist ein regelrechtes Buzzword im Internet in den letzten Monaten, doch was steckt
eigentlich hinter Ajax?
Ajax ist die Abkürzung für: Asyncronous JavaScript and XML
Ajax stellt eine Kombination aus länger existierenden Technologien da. JavaScript wird benutzt um
im Browser des Client eine Anfrage zum Server zu stellen. Wenn diese Anfrage vom Server
bearbeitet wurde, wird eine Funktion beim Client ausgeführt. Die Nachrichten die der Server
verschickt, sind hierbei oft in XML codiert. Die Codierung in XML ist jedoch nicht zwingen, es kann
auch eine Codierung als simpler Text erfolgen. XML bietet sich aber an um einen standardisierten
Mechanismus zum parsen von Daten zu haben.
Wie oben bereits erwähnt, führt der Server etwas aus und sendet eine Antwort als XML Dokument.
Die Implementierung auf der Serverseite kann in einer beliebigen Programmier oder Skriptsprache
realisiert werden. In diesem Tutorial und den Schaubildern verwende ich jedoch PHP als
serverseitige Skriptsprache.
Da die Anforderung vom Browser des Benutzers über JavaScript ausgelöst wird und mit JavaScript
auch die Verarbeitung der Antwort erfolgt, ist kein Reload der Webseite notwendig. In modernen
Webandwendungen wird diese Technologie gerne benutzt, um ein ähnliche Verhalten der
Anwendung wie bei einer herkömlichen Desktopanwendung zu realisieren.
Da ein gewisser Teil des Codes von Ajax Anwendungen immer ähnlich ist, gibt es im Internet
einige Frameworks die die Programmierung von Ajax Anwendungen erleichtern wollen.
Der Aufbau des ersten Ajax Programms
Wir sollten uns nun erstmal die Zeit nehmen dieses erste Ajax Programm zu analysieren.
Der grobe Aufbau sieht erstmal so aus:
1. Es gibt ein normales HTML Dokument mit Inline JavaScript Code.
2. Im Body des HTML Dokuments befindet sich ein div Container. Dieser Container hat die Id
"eins".
3. In diesem Container befindet sich ein Button. (Anmerkung: kein Submit). Dieser Button ruft
beim onclick Event die JavaScript Funktion doIt(); aus.
4. In der JavaScript Funktion doIt() wird zunächst das XMLHttpRequest Objekt erzeugt.
5. Mit diesem Request Objekt wird ein GET Request an die Url localhost/ajaxtutorial/eins/test.txt erzeugt.
6. Wenn das Request abgeschlossen ist wird eine Funktion aufgerufen. Diese wird hier als
"anonyme"JavaScript Funktion mit function erzeugt.
7. In der "anonymen" CallBack Funktion wird der HTML Inhalt des Element mit der Id "eins"
mit dem Inhalt des Response gefüllt. In diesem Fall wird also der Text "Hallo Welt" in den
div Container geschrieben.
Erzeugen des Ajax Request Objekts
try{
req = new XMLHttpRequest();
}
catch (e){
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (failed){
req = null;
}
}
}
In diesem Abschnitt wird das XMLHttpRequest Objekt angelegt. Seit der Version 7 ist dieses auch
im Internet Explorer von Microsoft verfügbar. Vorher in der Version 5 und 6 gab es im IE dieses
Objekt nicht, es gab jedoch ActiveXObject("Msxml2.XMLHTTP"); bzw.
ActiveXObject("Microsoft.XMLHTTP"); die die gleiche Funktionalität über sogar gleichnamige
Methoden bereitstellt.
Aus Gründen der Kompatibilität zu diesen Versionen sollte man also diese Struktur verwenden.
Das bedeutet beim IE 5 und 6 dass mit "new XMLHttpRequest();" bewusst eine Exception
ausgelöst wird und im catch Block dann für den IE das Objekt angelegt wird.
Unter folgender Url ist eine Spezifikation des XMLHttpRequest Objekts des W3C zu finden:
http://www.w3.org/TR/XMLHttpRequest/
Auslösen eines asyncronen Requests
req.open("GET", 'http://localhost/ajax-tutorial/eins/test.txt', true);
Über die Methode open wird ein neuer Request erzeugt. Diese Methode hat folgende Parameter:
• "GET" es handelt sich um einen HTTP GET Request, dazu später mehr.
• An die Url "http://localhost/ajax-tutorial/eins/test.txt" soll der Aufruf gerichtet sein.
Standardmässig ist beim Firefox z.b. nur ein Aufruf einer Adresse möglich die sich
unterhalb der gleichen Url wie das Aufrufende Skript befindet.
• "true" Dieser Parameter sagt, dass dieser Request asyncron ausgeführt werden soll.
Definition einer Callback Funktion
req.onreadystatechange = function(){
switch(req.readyState) {
case 4:
if(req.status!=200) {
alert("Fehler:"+req.status);
}else{
alert(req.responseText);
//schreibe die antwort in den div container mit der id content
document.getElementById('eins').innerHTML = '<strong>'+
req.responseText
+'</strong>';
}
break;
default:
return false;
break;
}
};
Mit dem Attribut onreadystatechange wird eine Funktion festgelegt, die aufgerufen wird, wenn der
request seinen readyState (abschlussStatus) ändert, z.b. wenn er erfolgreich abgeschlossen
wurde. In diesem Fall wird mit function(){} eine anonyme Funktion erstellt.
Zunächste wird in dieser Funktion der readyState geprüft ob er den gewünschten Wert 4 hat. Laut
der W3C spezifikation gibt es 5 Stati:
http://www.w3.org/TR/XMLHttpRequest/#xmlhttprequest-members
Innerhalb des Falls 4 (abgeschlossener Transfer) wird nun geprüft ob der HTTP Statuscode den
Wert 200 hat. 200 steht für eine Erfolgreiche Übertragung.
Die HTTP Statuscodes findet man ebefalls auch beim W3C:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Wenn alles erfolgreich gelaufen ist wird das Resultat der Abfrage (req.responseText) in das
Element mit der id "eins" geschrieben.
Header und Daten senden
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
req.send(null);
In diesem Bereich werden Felder des HTTP Headers gesetzt. Da keine Daten gesendet werden,
ist auch bei send nichts zum senden vorhanden.
Der HTML Inhalt
<body>
<div id="eins" style="width: 80%; height: 80%; border: dashed 1px;">
<input type="button" onclick="doIt();" value="Mach was!"/>
</div>
</body>
Im body des HTML Dokuments befindet sich lediglich ein div Container, in diesem Div Container
befindet sich ein Button, der die JavaScript Funktion doIt(); bei einem Klick ausführt.
XML und DOM ein Beispiel mit GET
In einem zweiten einfachen Beispiel möchte ich kurz auf die
Verwendung von DOM eingehen. In diesem Beispiel soll folgende
Funktionaltät realisiert werden:
• Der Benutzer kann ein englisches Wort eingeben.
• Der Browser übermittelt das Wort asynchron über Ajax zum
Webserver, nach der Eingabe. Diese übermittlung wird mit
einem GET Request gelöst, weil es nur ein Wort sein soll. Ajax Übersetzung in Action
• Der Webserver schaut beim Babelfish Webservice per
Soap nach Übersetzungen für dieses Wort in deutsch und französisch. Nachdem der
Webserver eine Antwort erhalten hat übermittelt er ein XML Dokument mit den
Übersetzungen an den Client.
• Der Client wertet dieses XML Dokument mit DOM aus und schreibt die Werte in die
passenden Formularfelder.
Um den Quelltext so einfach wie Möglich zu halten wird auf unnötige Designelemente verzichtet.
Das JavaScript benutze ich als Inline Code im HTML Dokument. Bei einer ernsthaften
Implementierung sollte hierfür natürlich eine externe Datei verwendet werden. Das gleiche gilt für
den CSS code.
Die Realisierung auf der Serverseite erfolgt mit PHP5, da hier der SoapClient relativ einfach
genutzt werden kann.
Es dauert etwas länger bist eine Antwort erscheint, dabei muss man aber auch beachten was
hinter der Kulisse passiert:
•
•
•
•
•
Anfrage via Ajax.
Der Webserver läd eine WSDL Datei die den Webservice beschreibt.
Auf dem Webserver abfrage eines Webservice via Soap.
zurücksenden der Antwort.
parsen und schreiben der Ergebnisse.
Alle diese Vorgänge brauchen etwas Zeit und ist abhängig von der Netzanbinung der beteiligen
Server. Ich denke aber das man hieran sehen kann was mit Ajax möglich ist.
Beispiel: Server, Zugriff auf Babelfish via Soap
Der in PHP geschriebene Server halt folgenden einfachen Aufbau:
<?php
header("Content-Type: text/xml");
$english = mysql_escape_string($_REQUEST['translate']);
$trans = new SoapClient("http://www.xmethods.net/sd/2001/".
"BabelFishService.wsdl");
try{
$german = $trans->BabelFish("en_de",$english);
$french = $trans->BabelFish("en_fr",$english);
}
catch(SoapFault $e){
$english = "not found";
$german = "not found";
$french = "not found";
}
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
?>
<translation>
<english><?php echo $english; ?></english>
<german> <?php echo $german; ?></german>
<french> <?php echo $french; ?></french>
</translation>
Beispiel: Die in XML codierte Übersetzung als Antwort
Die Übersetzung des Strings "car" würde zum Beispiel folgendes XML Dokument als Antwort
generieren:
<translation>
<english>car</english>
<german> Auto </german>
<french> voiture </french>
</translation>
Das Programm zur Übersetzung ist nun geschrieben. Im Vergleich zum ersten Beispiel hat sich
garnicht so viel geändert. Im nächsten Abschnitt ist eine detailierte Analyse der Bereiche zu finden
die sich geändert haben.
Analyse des Beispiels
Das die Funktion, die beim beenden des Requests ausgeführt wird diesmal etwas grösser
geworden ist wurde diese in handleTranslation ausgelagert und der Name der Funktion bei
onreadystatechange übergeben.
Verarbeitung der Antwort mittels DOM in handleTranslation
Da die Antwort XML kodiert ist erfolgt die Auswertung mittels DOM:
//felder des formulars
german_field = document.getElementById("german");
french_field = document.getElementById("french");
//antwort des servers
xml = req.responseXML;
german_resp = xml.getElementsByTagName("german")[0];
french_resp = xml.getElementsByTagName("french")[0];
//schreiben des ergebnisses
german_field.value = german_resp.firstChild.nodeValue;
french_field.value = french_resp.firstChild.nodeValue;
In den ersten drei Zeilen wird lediglich das Formular Feld, in das später geschrieben werden soll in
einer Variable gespeichert.
In den nächsten drei Zeilen wird mit "req.responseXML" die XML antwort gelesen. Es wird jeweiles
der Knoten mit dem Tag german und french zwischengespeichert. In den danach folgenden drei
Zeilen wird das Ergebnis innerhalb dieser Tags in die Formularfelder geschrieben.
So steht zum Schluss die Übersetzung in den dafür vorgesehenen Feldern.
Übermittlung via GET
In diesem Beispiel erfolgt die Übermittlung mit einem HTTP GET Request. Folgende stelle im
Code ist dafür intressant:
//anfrage erstellen (GET, url ist localhost,
//request ist asynchron
var url = 'http://localhost/ajax-tutorial/zwei/ajax.php?translate='+
document.getElementById('myword').value;
req.open("GET", url, true);
In der Variable "url" wird zunächst die Url zusammengebaut in dem das zu übersetzende Wort aus
dem entsprechenden Textfeld ausgelesen wird und an die Url angehängt wird. Für das Beispiel mit
dem Auto hätte die Url also folgenden Wert:
"http://localhost/ajax-tutorial/zwei/ajax.php?translation=car"
Muss ich XML benutzen?
Wie man an diesem Beispiel sieht, hat XML einige Vor und Nachteile. Zunächst einmal die Vorteile:
• XML ist weit verbreitet eine Verarbeitung des XML Dokuments ist in allen
Programmiersprachen meisst mit eingenen Parsern möglich.
• Wenn man DOM beherrscht ist eine Verarbeitung einfach möglich.
• XML liefert eine Möglichkeit der validiering eines Dokuments quasi mit.
XML bringt aber auch ein paar Nachteile mit sich:
• Die Dokumente die zurück geschickt haben, enthalten viel an Drumherum (Overhead) aber
nur wenig Nutzbare Daten.
• Mit XML kommt zu JavaSkript und der serverseitigen Programmiersprache eine weitere
Technologie hinzu die man beherrschen muss.
• Sich in DOM einzuarbeiten für ein paar kleine Projekte kann u.U zu aufwändig sein.
Aus den oben genannten Gründen gibt es JSON. JSON ermöglicht es auf dem Server
Datenstrukturen wie z.B. einen Array in das JSON Format zu serialisieren. Im Client JavaScript
kann diese serialisierte Struktur wieder zusammengebaut (deserialisiert) werden und genutzt
werden.
Quelle: http://www.admin-wissen.de/