AJAX:Getting Started
Aus MDC
Dieser Artikel führt in die Grundlagen von AJAX ein und beschreibt zwei einfache praktische Beispiele, die einen ersten Einblick liefern.
Inhaltsverzeichnis |
[bearbeiten] Was ist AJAX?
AJAX (Asynchronous JavaScript and XML) ist ein neu geprägter Ausdruck für zwei mächtige Browsertechniken welche bereits seit Jahren existieren, jedoch bislang von Webentwicklern nicht beachtet wurden. Erst seit kurzem erhalten diese Techniken neue Beachtung, seit Services wie Google Mail, Google Suggest oder Google Maps erschienen sind.
Mit den zwei erwähnten Techniken kann man
- Requests an den Server absetzen, ohne die Seite neu laden zu müssen
- XML-Dokumente parsen und bearbeiten
[bearbeiten] Schritt 1 – sag "Bitte!" oder Wie mache ich einen HTTP-Request
Um einen HTTP-Request mittels JavaScript an einen Server absetzen zu können, benötigt man eine Instanz einer Klasse, welche diese Funktionalität bietet. Solch eine Klasse, genannt XMLHTTP, wurde ursprünglich im Internet Explorer als ein ActiveX-Objekt eingeführt. Später implementierten Mozilla, Safari und andere Browser eine Klasse namens XMLHttpRequest, welche die Methoden und Eigenschaften des originalen ActiveX-Objektes von Microsoft unterstützt.
Um nun eine browserübergreifende Instanz der benötigten Klasse zu erzeugen, kann man folgendes tun:
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
(Zur Veranschaulichung ist der im obigen Beispiel dargestellte Code zur Erzeugung einer XMLHTTP-Instanz vereinfacht dargestellt. Für ein wirklichkeitsgetreueres Beispiel sei auf Schritt 3 verwiesen.)
Einige Versionen einiger Mozilla-basierter Browser werden nicht korrekt arbeiten, wenn die Antwort des Servers keinen XML mime-type im Header hat. Um dem entgegenzuwirken, kann man einen zusätzlichen Methodenaufruf absetzen, um den vom Server gesendeten Header zu überschreiben - für den Fall, dass dessen mime-type nicht text/xml lautet.
http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
Im nächsten Schritt entscheidet man, was zu tun ist, nachdem man vom Server eine Antwort zu dem abgesetzten Request bekommen hat. An dieser Stelle muss man dem HTTP Request-Objekt lediglich mitteilen, welche JavaScript-Funktion die Antwort abarbeiten soll.
Dies erreicht man, indem man die onreadystatechange-Eigenschaft des Objektes genauso nennt wie die JavaScript-Funktion, welche man benutzen möchte, ungefähr so:
http_request.onreadystatechange = nameDerFunktion;
Es ist zu beachten, dass nach dem Funktionsnamen keine Klammern auftauchen und der Funktion keine Parameter übergeben werden. Des weiteren kann man anstelle der Angabe eines Funktionsnamens die Funktion "on the fly" definieren, etwa so:
http_request.onreadystatechange = function(){
// mach etwas
};
Nachdem wir beschrieben haben was mit der empfangenen Antwort geschehen soll, muss der Request abgesetzt werden. Dazu ruft man die Methoden open() und send() der HTTP-Request Klasse auf, etwa so:
http_request.open('GET', 'http://www.beispiel.org/eine.datei', true);
http_request.send(null);
- Der erste Parameter des Aufrufs der Methode open() ist die HTTP-Request-Methode - GET, POST, HEAD oder eine beliebige andere Methode, welche eingesetzt werden soll und welche vom verwendeten Server unterstützt wird. Die Methode sollte nach dem HTTP-Standard groß geschrieben werden, da andernfalls einige Browser (z.B. Firefox) die Anfrage nicht verarbeiten. Für mehr Informationen zu den möglichen HTTP-Request-Methoden sei auf die W3C Spezifikationen verwiesen.
- Der zweite Parameter ist die URL der angeforderten Seite. Aus Sicherheitsgründen können keine Seiten auf 3rd-party Domains angefordert werden. Es muss sichergestellt werden, dass der exakte Domainname auf allen Seiten benutzt wird; andernfalls bekommt man einen 'permission denied'-Fehler beim Aufruf von
open(). Ein beliebter Fallstrick ist der Aufruf einer Seite mittels 'domain.tld', wobei die gewünschte Seite jedoch 'www.domain.tld' lautet. - Der dritte Parameter gibt an, ob der Request asynchron sein soll. Wenn er auf
truegesetzt ist, wird die JavaScript-Funktion weiter ausgeführt, während die Antwort des Servers noch aussteht. Dies ist das A in AJAX.
Der Parameter der send()-Methode können beliebige Daten sein, die an den Server per POST gesendet werden sollen. Die Daten sollten in Form einer Suchanfrage formuliert sein, etwa so:
name=wert&anderername=andererwert&so=weiter
Bei der Übergabe der Daten per POST ist zu beachten, dass der MIME-Typ der Anfrage wie folgt angepasst werden muss:
http_request.open('POST', 'http://www.beispiel.org/eine.datei', true);
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http_request.send('name=wert&anderername=andererwert&so=weiter');
Andernfalls wird der Server die per POST übergebenen Daten ignorieren. Wichtig dabei ist, dass die 'setRequestHeader'-function nach der 'open'-function aufgerufen wird, da es sonst zu einem Fehler kommt.
[bearbeiten] Schritt 2 – "Bitteschön!" oder Verarbeiten der Antwort des Servers
Zur Erinnerung: beim Abschicken des Requests wurde der Name einer JavaScript-Funktion mitgegeben, welche die Antwort abarbeiten soll.
http_request.onreadystatechange = nameDerFunktion;
Schauen wir mal, was diese Funktion tun sollte. Zuerst muss die Funktion den Status des Requests abfragen. Hat dieser den Wert 4, bedeutet das, dass die Antwort des Servers vollständig empfangen wurde und dass sie nun bearbeitet werden kann.
if (http_request.readyState == 4) {
// alles in Ordnung, Antwort wurde empfangen
} else {
// noch nicht bereit
}
Die komplette Liste der Werte sieht wie folgt aus:
- 0 (nicht initialisiert)
- 1 (lade)
- 2 (geladen)
- 3 (interaktiv)
- 4 (vollständig)
(Quelle)
Als nächstes muss die Antwort des HTTP-Servers geprüft werden. Alle möglichen Codes sind auf der
W3C-Seite aufgelistet. Für unsere Zwecke interessiert nur der Antwortcode 200 OK.
if (http_request.status == 200) {
// perfekt!
} else {
// die Anfrage enthielt Fehler;
// die Antwort war z.B. 404 (nicht gefunden)
// oder 500 (interner Server-Fehler)
}
Nachdem nun der Status des Requests und der HTTP-Status geprüft wurden, kann man mit den vom Server gesendeten Daten anstellen, was man möchte. Für den Zugriff auf die Daten gibt es zwei Möglichkeiten:
-
http_request.responseText– gibt die Antwort des Servers als einen Textstring zurück -
http_request.responseXML– gibt die Antwort des Servers als einXMLDocument-Objekt zurück, welches man mittels der JavaScript DOM-Funktionen verarbeiten kann
[bearbeiten] Schritt 3 – "Jetzt alle zusammen!" - Ein einfaches Beispiel
Jetzt führen wir alles zusammen und machen einen einfachen HTTP-Request.
Per JavaScript wird ein HTML-Dokument namens test.html angefordert, welches den Text "Ich bin ein Test." enthält. Anschliessend geben wir per alert() den Inhalt dieser Datei aus.
<script type="text/javascript" language="javascript">
var http_request = false;
function macheRequest(url) {
http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
// zu dieser Zeile siehe weiter unten
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Ende :( Kann keine XMLHTTP-Instanz erzeugen');
return false;
}
http_request.onreadystatechange = alertInhalt;
http_request.open('GET', url, true);
http_request.send(null);
}
function alertInhalt() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
alert(http_request.responseText);
} else {
alert('Bei dem Request ist ein Problem aufgetreten.');
}
}
}
</script>
<span
style="cursor: pointer; text-decoration: underline; color: blue"
onclick="macheRequest('test.html')">Einen Request absetzen
</span>
Erklärung zu diesem Beispiel:
- Der Benutzer klickt im Browser auf den Link "Einen Request absetzen";
- Dies ruft die Methode
macheRequest()mit einem Parameter – der Name einer HTML-Datei im gleichen Verzeichnis (test.html) - Der Request wird abgesetzt und anschliessend (
onreadystatechange) wirdalertInhalt()ausgeführt; -
alertInhalt()prüft, ob die Antwort empfangen wurde und ob sie OK (Status 200) ist und gibt anschliessend peralert()den Inhalt der Dateitest.htmlaus.
Das Beispiel kann hier getestet werden; den Inhalt der Testdatei kann man sich hier ansehen.
Hinweis: Die Zeile http_request.overrideMimeType('text/xml'); gibt in Firefox 1.5b Fehler auf der JavaScript-Konsole aus (dokumentiert unter https://bugzilla.mozilla.org/show_bug.cgi?id=311724), wenn die per XMLHttpRequest aufgerufene Seite kein valides XML ist (z.B. purer Text).
Wenn man einen 'Syntax Error' oder einen 'Not Well Formed Error' im Browser bekommt, und man nicht versucht, eine XML-Seite per XMLHttpRequest zu laden, kann man diese Zeile entfernen.
[bearbeiten] Schritt 4 – "Akte X" oder Verarbeiten der XML-Response
Im vorhergehenden Beispiel wurde, nachdem die Antwort des HTTP-Requests empfangen wurde, die responseText-Eigenschaft des Request-Objektes benutzt, welche den Inhalt der Datei test.html enthielt. Nun versuchen wir einmal die responseXML-Eigenschaft.
Zuerst erzeugen wir ein valides XML-Dokument, welches später angefordert wird. Das Dokument (test.xml) hat folgenden Inhalt:
<?xml version="1.0" ?>
<root>
Ich bin ein Test.
</root>
Im Skript brauchen wir nur die Zeile mit macheRequest() wie folgt zu ändern:
...
onclick="macheRequest('test.xml')">
...
Danach muss man in alertInhalt() die Zeile alert(http_request.responseText); ersetzen durch:
var xmldoc = http_request.responseXML;
var root_node = xmldoc.getElementsByTagName('root').item(0);
alert(root_node.firstChild.data);
Jetzt werden DOM-Methoden benutzt, um Daten aus dem XML-Dokument zu lesen, welches als XMLDocument-Objekt mittels responseXML gelesen wurde. Die Datei test.xml kann man sich hier ansehen, das geänderte Test-Skript hier.
Für weiterführende Informationen zu den DOM-Methoden sei auf das Dokument Mozilla's DOM Implementierung verwiesen.