Tutorial: Ajax (5)
siehe auch:
(1): Was ist Ajax?
(2): Warum heißt Ajax so? Wo kann ich Ajax in Aktion sehen?
(3): Worin besteht die Ajax-Schnittstelle? Wie wird Ajax standardisiert?
(4): Welche Nachteile hat Ajax? Wie sicher ist Ajax?
Ein einfacher Ajax-Kernel
Die Ajax-Schnittstelle selbst ist vergleichsweise überschaubar. Das XML-HTTP-Objekt lässt sich, wie bereits beschrieben, mit einer kleinen Browserweiche zuverlässig in allen modernen Browsern initialisieren. Die Aufgabe des Objekts besteht darin, HTTP-Requests an den Webserver abzusetzen und nachfolgende HTTP-Responses vom Webserver zu empfangen. Es bietet sich daher an, diese Aufgabe in eine kleine, wiederverwendbare Code-Bibliothek (die wir den „Ajax-Kernel“ nennen wollen) zu packen.
Die Funktionen
Für unsere einfachen Beispiele und für viele Anwendungsfälle in der Praxis genügt der nachfolgend vorgestellte Ajax-Kernel. Je nach Aufgabenstellung können komplexere Varianten dieses Kernels erforderlich werden. Beispielsweise dann, wenn POST-Daten über die Ajax-Schnittstelle an den Webserver übertragen werden sollen (unser Beispiel-Kernel sendet nur GET-Requests).
Eine Möglichkeit besteht darin, den nachfolgenden Code in einer eigenen JavaScript-Datei zu speichern – nennen wir sie ajax.js:
var httpRequest = false; var noResult = "Kein Ergebnis"; // =================================== function doHttpRequest(url, outputId) { httpRequest = false; if(window.XMLHttpRequest) // Mozilla, Safari,... httpRequest = new XMLHttpRequest(); else if(window.ActiveXObject) { // IE try { httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if(!httpRequest) return false; httpRequest.onreadystatechange = function() { if(httpRequest.readyState == 4) { if(httpRequest.status == 200) handleHttpResponse(httpRequest.responseText, outputId); else return false; } else return false; } httpRequest.open('get', url, true); httpRequest.send(null); } function handleHttpResponse(content, outputId) { if(!document.getElementById) return false; if(!document.getElementById(outputId)) return false; if(content == "FALSE") document.getElementById(outputId).innerHTML = noResult; else document.getElementById(outputId).innerHTML = content; }
Um die Funktionsweise des XML-HTTP-Objekts zu verstehen, ist es allerdings wichtig, entscheidende Details aus diesem Code zu verstehen.
Der Code besteht aus zwei Funktionen:
- Die Funktion
doHttpRequest()
ist die zentrale Steuerfunktion. Sie wird von anderem JavaScript-Code, der den Ajax-Kernel verwenden möchte, aufgerufen. - Die Funktion
handleHttpResponse()
ist eine interne Funktion, die nur vondoHttpRequest()
aufgerufen wird.
Zu Beginn des Ajax-Kernels werden ferner zwei globale Variablen definiert:
- Die Variable
httpRequest
speichert eine Instanz des XML-HTTP-Objekts. Sie wird mit dem booleschen Wertfalse
initialisiert. - Die Variable
noResult
wird mit einem Text initialisiert, der ausgegeben werden soll, wenn eine Ajax-Operation keine Daten vom Server erhält.
Die Funktion doHTTPRequest()
Die Funktion doHTTPRequest()
erwartet zwei Parameter:
url
ist die vollständige URL-Adresse eines Scripts auf dem Webserver, das über Ajax aufgerufen werden soll. Dieses Script — es kann sich beispielsweise um ein PHP-Script handeln — kann beispielsweise Daten aus einer Datenbank auslesen, in HTML-Form aufbereiten und diesen aufbereiteten HTML-Code zurückgeben.output_id
ist der id-Attributwert eines HTML-Elements im aktuell im Browser angezeigten HTML-Dokument. In dieses Element wird der HTML-Code, den das miturl
bezeichnete Script erzeugt, dynamisch eingebaut — und genau dadurch entsteht der Effekt, den Ajax ausmacht.
Den ersten Teil der Funktion doHTTPRequest()
kennen Sie bereits. Mittels einer geeigneten Browser-Weiche wird eine Instanz des XML-HTTP-Objekts erzeugt, was praktisch in allen modernen Browsern gelingt.
Der neue Teil beginnt mit httpRequest.onreadystatechange = function()
. Allein dieses Konstrukt ist jedoch sehr erklärungsbedürftig.
onreadystatechange
sieht aus wie eine Eigenschaft des XML-HTTP-Objekts. Das Präfix on...
signalisiert jedoch, dass es sich um einen Event-Handler handelt, also um ein Ereignis, bei dessen Eintreffen etwas Bestimmtes geschehen soll. Deshalb wird dieser Eigenschaft auch kein einfacher Wert wie eine Zahl oder eine Zeichenkette zugewiesen, sondern eine Prozedur, die bei Eintreffen des Ereignisses ausgeführt werden soll. Die Prozedur wird eingeschlossen in:
httpRequest.onreadystatechange = function() { // hier der Code der Prozedur }
Mit function()
wird eine unbenannte Funktion aufgerufen, die man sich als eine mehrfach aufrufbare Subroutine innerhalb der Funktion doHTTPRequest()
vorstellen muss. In unserem Fall lautet der Code innerhalb der Prozedur:
if(httpRequest.readyState == 4) { if(httpRequest.status == 200) handleHttpResponse(httpRequest.responseText, outputId); else return false; } else return false;
readyState
ist eine „echte“ Eigenschaft des XML-HTTP-Objekts. In der Eigenschaft wird in Form eines Integer-Werts gespeichert, in welcher Phase sich eine aktuelle, vom XML-HTTP-Objekt gestartete HTTP-Kommunikation befindet. Mögliche Werte sind 0 bis 4. Eine vollständige HTTP-Kommunikation durchläuft nacheinander alle fünf Werte:
0 ist einfach der Anfangswert.
1 bedeutet, dass die HTTP-Verbindung zum Webserver erfolgreich zustande kam.
2 bedeutet, dass der HTTP-Request vollständig übertragen wurde.
3 bedeutet, dass die HTTP-Header der Server-Antwort empfangen wurden.
4 bedeutet, dass die Server-Antwort komplett übertragen wurde.
Der Event-Handler onreadystatechange
bewirkt, dass bei jeder Änderung des Werts von readyState
die Prozedur, die onreadystatechange
zugewiesen ist, erneut ausgeführt wird. Innerhalb der Prozedur könnten wir also auf jede genannte Phase der HTTP-Kommunikation mit Script-Code reagieren. Im Beispiel reagieren wir jedoch nur auf die letzte Phase, nämlich mit if(httpRequest.readyState == 4
). Die übrigen Phasen werden durch durch else return false
ignoriert.
Wenn readyState
den Wert 4 hat, ist also die HTTP-Kommunikation abgeschlossen und der Webserver hat seine Antwort auf eine Anfrage gesendet. Um die Antwort auszuwerten, ist es zweckmäßig, zunächst den HTTP-Statuscode der Server-Antwort auszulesen. Dieser ist in der Eigenschaft status
des XML-HTTP-Objekts gespeichert. In unserem Beispiel erwarten wir für den „Gutfall“ den HTTP-Status-Code 200. Dieser Code bedeutet, dass der Server den HTTP-Request erfolgreich bearbeiten konnte und die angeforderten Daten senden konnte.
Auf den HTTP-Status-Code 200 reagieren wir mit einem Aufruf der zweiten Funktion unseres Ajax-Kernels: handleHTTPResponse()
, auf die wir weiter unten noch näher eingehen werden. Der Funktion werden zwei Parameter übergeben, nämlich die vom Webserver erhaltenen Nutzdaten, sowie den id-Attributwert eines Elements im aktuell angezeigten HTML-Dokument, innerhalb dessen die Daten ausgegeben werden sollen. Was letzteres betrifft, so reichen wir den Parameter outputId
einfach durch.
Die eigentlichen Daten übergeben wir mit einer weiteren Eigenschaft des XML-HTTP-Objekts, nämlich httpRequest.responseText
. Diese speichert die vom Webserver erhaltenen Nutzdaten als normale Zeichenkette. Wenn also beispielsweise ein über Ajax aufgerufenes PHP-Script auf dem Server HTML-Code generiert und zurückgibt, ist in der Objekteigenschaft responseText
dieser HTML-Code enthalten.
Die beiden letzten Anweisungen der Funktion doHttpRequest()
sind einigermaßen verständlich. Mit httpRequest.open('get', url, true)
wird die Methode open()
des XML-HTTP-Objekts aufgerufen. Diese Methode setzt einen HTTP-Request an den Server ab. Als erster Parameter wird die Request-Methode angegeben. In unserem Fall ist das die GET-Methode. Der zweite Parameter übergibt die URL-Adresse, an die der HTTP-Request gehen soll. Der dritte Parameter ist ein true
-false
-Wert. Wenn auf true
gesetzt (was auch die Default-Einstellung ist), wird die JavaScript-Funktion weiter ausgeführt, auch wenn noch keine Server-Antwort vorliegt. Wenn auf false
gesetzt, wartet JavaScript mit der Ausführung der weiteren Anweisungen so lange, bis die Server-Antwort vorliegt. Die Funktion ist also in unserem Fall eigentlich längst beendet, wenn die Antwortdaten vom Webserver eintreffen. Um sie dennoch abzufangen, haben wir zuvor die Ereignisbehandlung für onreadystatechange
definiert.
Mit httpRequest.send(null)
wird dem Server mitgeteilt, dass außer dem Request selber kein Daten an den Server gesendet werden. Falls dem aufzurufenden Script auf dem Server Daten übergeben werden sollen, können Sie anstelle von null
einen Query-String übergeben, der nach den dafür üblichen Regeln aufgebaut ist, also z.B.:
httpRequest.send("name=value&another_name=another_value");
Die Funktion handleHttpResponse()
Die Funktion handleHttpResponse()
erwartet zwei Parameter:
content
ist eine beliebige Zeichenkette, die Text bzw. HTML-Code enthalten sollte.output_id
ist der id-Attributwert eines HTML-Elements im aktuell im Browser angezeigten HTML-Dokument. In dieses Element wird der HTML-Code, der mitcontent
übergeben wird, dynamisch eingebaut.
Die Funktion dient wie schon erwähnt nur als Subroutine für die Ajax-Kernel-Hauptfunktion doHTTPRequest()
. Beim Parameter content
besteht zusätzlich die Möglichkeit, anstelle einer Zeichenkette den Booleschen Wert false
zu übergeben. In diesem Fall setzt die Funktion als Inhalt des mit outputId
bezeichneten Elements den Inhalt der globalen Variablen noResult
ein, die zu Beginn des Kernel-Scripts initialisiert wurde.
0 Comments: