AJAX-Grundlagen: Das neue Web

30.05.2006 von Thomas Wölfer
Das Web wird noch dynamischer. Mit Ajax steht eine Sammlung an Technologien zur Verfügung, die bei der Implementierung von interaktiven Web-Anwendungen verwendet werden kann. In diesem Beitrag erlernen Sie alle Grundlagen, um Ajax in Ihren eigenen Anwendungen anwenden zu können.

Das Akronym Ajax steht für „Asynchronous Javascript And XML“. Im Kern geht es dabei darum, Webseiten interaktiver zu gestalten. Bereits mit dem Internet Explorer 5 waren eigentlich alle für Ajax benötigten Komponenten in einem gängigen Browser vorhanden, fanden aber keine breite Anwendung. Der Microsoft-Konkurrent Google dagegen schaffte es mit seinem Ajax-basierten E-Mail-Dienst Google Mail einen wahren Ajax-Boom auszulösen.

Die Idee hinter Ajax besteht daraus, Teile einer Webseite asynchron nachzuladen und den Inhalt der Webseite dadurch zu verändern. Das bedeutet, dass bei einer Veränderung nicht die komplette Seite neu geladen wird, sondern lediglich die geänderten Inhalten. Dafür wird ein so genannter XMLHttpRequest aus einem JavaScript Script heraus ausgelöst. Dieser Request erfragt von einem Server Inhalte, die typischerweise per XML an das JavaScript zurück gesendet werden. Das Script wertet dann dieses XML aus. Die Daten aus dem XML setzt das Script dann um und ändert mit Hilfe des DOM (Document Object Model) die Website entsprechend.

Stückchenweise laden

Ein praxisnahes Beispiel für die Anwendung ist ein Diskussionsforum, dessen Diskussionen im HTML als Baum dargestellt werden. Um einen Beitrag zu lesen, muss der Surfer auf den Titel des Beitrages im Baum klicken. Im klassischen Modell wird dazu ein Request an den Server gesendet, und eine vollständige Seite die zusätzlich zum Baum den Text des Beitrages enthält. Beim Modell mit Ajax würde als Reaktion auf die Serveranfrage nur der Text des Beitrages geliefert werden: Ein Javascript-Programm wäre dann dafür zuständig, diesen Text auf der ansonsten nicht veränderten Seite einzublenden.

Für die Durchführung dieser Anfrage gab es bei älteren Internet-Explorern seit Version 5 ein ActiveX Objekt. Der IE 7 wird, so wie andere Browser das heute schon tun, ein entsprechendes Objekt nativ zur Verfügung stellen. Die aktuelle XMLHttpRequest-API des Internet Explorer gibt es bei MSDN, die von Mozilla ist ebenfalls verfügbar.

Der eigentliche Trick bei Ajax ist der XMLHttpRequest – der kann nämlich asynchron stattfinden. Asynchron bedeutet in diesem Zusammenhang, asynchron zum Aufbau der restlichen Seite, und auch asynchron zu den auf der Seite laufenden Skripten. Das bedeutet, dass ein Download von Daten per HTTP angestoßen werden kann, und dass die Daten heruntergeladen werden können, ohne das dadurch die Interaktion des Surfers mit der Seite leidet. Der Aufbau der angeforderten Seite läuft also im Hintergrund ab.

Asynchron laden - nichts blockieren

Zusätzlich zum asynchronen Download von Teilen des Inhalts wird unter Ajax auch häufig eine stark interaktive HTML-Seite verstanden, die Interaktion aber mit klassischen Mitteln wie CSS und Javascript erreicht: Dabei erhält der Anwender bessere Hinweise auf die Funktionsweise der Seite zum Beispiel durch überlagernde Effekte.

Für die Verwendung von Ajax auf Webseiten gibt es eine ganze Reihe an Frameworks, auf all diese einzugehen, würde aber den Rahmen des Beitrags sprengen. Stattdessen erklärt der Beitrag im Folgenden die grundlegende Funktionsweise von Ajax anhand eines Workshops.

Das Beispiel implementiert einen Teil der Client-Site eines typischen Webforums. Das Forum hat eine Thread-Seite, auf der die Beiträge untereinander angezeigt werden. Unter jeder Thread-Überschrift werden dabei die Überschriften der Antworten angezeigt. Für das Beispiel wurde Ajax dann verwendet, um die eigentlichen Nachrichten sichtbar zu machen: Der Benutzer des Forums kann eine Überschrift anklicken, und der Text der Nachricht wird daraufhin unterhalb der Überschrift aber oberhalb der nächsten Antwort eingeblendet.

Grundsätzlich ließe sich das auch so lösen, dass einfach die Inhalte aller Nachrichten in unsichtbaren DIV-Elementen vollständig geladen werden. Der Klick auf die Überschrift würde dann ein Javascript ausführen, das den entsprechenden Textkörper sichtbar macht. Der Nachteil dabei ist natürlich der, dass der komplette Text aller Nachrichten immer mit heruntergeladen werden muss.

Praxis-Workshop: Ein Ajax-Forum

Das Beispiel arbeitet wie folgt: Der Mausklick auf die Überschrift startet Javascript, das seinerseits den benötigten Text per Ajax nachlädt und an passender Stelle einbaut. Der HTML-Body der Thread-Seite wird vom Server wie folgt generiert:

<div id="p1" onclick="GetText('p1')">Die erste Überschrift zum Thread</div>
<div id="p2" onclick="GetText('p2')">Die erste Antwort</div>
<div id="p3" onclick="GetText('p3')">Die zweite Antwort</div>

Die einzelnen Überschriften befinden sich also jeweils innerhalb eines DIV-Elementes und haben auch eine jeweils eindeutige ID. In der Praxis würde man dafür vermutlich die ID des zugehörigen Datensatzes aus der Datenbank verwenden, in der sich die Nachrichten befinden. Für jedes DIV wird ein „onclick“-Eventhandler gesetzt. In der Praxis würde man dies sicherlich ebenfalls per Javascript tun, um das Beispiel einfacher zu gestalten wurde darauf hier aber verzichtet. Der Click-Handler hat einen Parameter, und zwar die ID des DIVs.

Ein Klick - Ein Download

Mit dem Click-Handler beginnt die eigentliche Ajax-Implementierung. Jede Implementierung setzt sich aus drei Kernstücken zusammen: Eine Funktion, die das XMLHttpRequest-Objekt erzeugt und den Download anstößt, eine Funktion die mitbekommt, wenn der Download beendet wurde, die dritte Funktion wertet die Daten anschließend aus. GetText() ist hier die erste Funktion, die den Download anstößt.

var getter = null;
function GetText( id) {
if (getter != null && getter.readyState != 0 && getter.readyState != 4) {
getter.abort();
}
try {
getter = new XMLHttpRequest();
}
catch (error) {
try {
getter = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (error) {
getter = null;
return false;
}
}
getter.onreadystatechange = ReadystateChanged;
getter.open( "GET", id + ".xml");
getter.send(null);
return true;
}

Zunächst gibt es dazu eine Variable „getter“. Diese nimmt eine Instanz des XMLHttpRequest-Objektes auf und ist zunächst auf null gesetzt. Zu Beginn der Funktion wird dann überprüft, ob es bereits ein solches Objekt gibt, und ob sich dieses momentan damit befasst, etwas herunterzuladen.

Ist das der Fall, so wird der Vorgang mit abort() abgebrochen. Sinn der Sache ist es, nicht zu viele parallele Downloads anzustoßen - wobei multiple Downloads in der Praxis wohl eher kein wirklich großes Problem darstellen. Danach wird innerhalb es try/catch-Blockes versucht, ein XMLHttpRequest-Objekt zu instanziieren.

Funktion Zwei: Onreadystatechanged

Am Ende des äußeren Try-Blockes angelangt, liegt nun also ein passendes Objekt vor. Das XMLHttpRequest-Objekt hat ein Event namens „onreadystatechanged“. Dieses Event wird im Zuge des Download-Vorganges mehrfach ausgelöst, ihm wird im Code der Eventhandler „ReadystateChanged“ zugewiesen.

Im nächsten Schritt wird dem Objekt die Methode für den Download (GET), sowie die herunterzuladende URL angegeben. Für dieses Beispiel wird davon ausgegangen, das sich die einzelnen Beiträge des Forums in separaten XML-Dateien befinden, die die ID des Postings als Namen verwenden. In der Praxis würde man hier vermutlich eher ein PHP- oder ASP-Skript ansprechen, dem die ID als Parameter übergeben wird. Für die Verwendung von Ajax ist es aber ohne Belang, woher die Daten auf dem Webserver stammen, beziehungsweise wie die Antwortdaten für die HTTP-Anfrage generiert werden.

Im Anschluss übergibt send() die Anfrage. Das ganze läuft asynchron ab, das bedeutet, der Aufruf von send() kommt sofort zurück, das Skript kann weitere Aufhaben übernehmen.

Daraufhin tritt der zweite Schritt von Ajax in Aktion: Der Eventhandler für „onreadystatechanged“ wird aufgerufen. Im Beispiel ist das die Funktion ReadyStateChanged().

function ReadystateChanged() {
if (getter.readyState == 4) {
if (getter.status == 200) {
InsertContent();
} else {
alert("Fehler: " + getter.statusText);
}
}
return true;
}

Statusinformation

Während des Datentransfers wird der Eventhandler mehrfach aufgerufen. Dabei lässt sich der aktuelle Zustand des Transfers anhand des Members „readyState“ des XMLHttpRequest-Objektes überprüfen. Zur Verfügung steht ein Wert von 0 bis4, wobei 4 bedeutet, dass die Daten komplett geladen wurden und zur Verfügung stehen. In der unten stehenden Tabelle finden Sie die Bezeichnungen aller Werte, weitere Informationen gibt die MSDN-Dokumentation.

Wert

Bedeutung

0

Das Objekt wurde erstellt, aber noch nicht initialisiert

1

Das Objekt wurde erstellt, aber die send()-Methode noch nicht aufgerufen

2

Die send()-Methode wurde aufgerufen, aber Header und Status sind noch nicht verfügbar

3

Einige Daten wurden bereits empfangen, aber die Übertragung ist noch nicht komplett

4

Alle Daten wurden empfangen und stehen zur Verfügung

Zusätzlich zum „readyState“ hat das XMLHttpRequest-Objekt auch noch den „status“-Member. Dessen Wert gibt den HTTP-Status des Transfers an: Steht dieser auf 200, so ist der Transfer nicht nur abgeschlossen, sondern hat auch funktioniert. Beide Member werden in ReadystateChanged() abgeprüft - im Fehlerfall wird dabei eine Nachricht per alert() angezeigt.

Funktion Drei: Auswertung und Abschluss

Ist der Transfer abgeschlossen tritt der dritte Ajax-Zustand ein: Die Daten werden ausgewertet. Im Beispiel passiert das mit der Funktion InsertContent().

function InsertContent() {
var node = getter.responseXML.getElementsByTagName("message")[0];
var target = node.getAttribute("target");
var msgNode = document.createElement("div");
var parentNode = document.getElementById( target);
parentNode.appendChild(msgNode);
msgNode.textContent = node.firstChild.nodeValue; // ff
msgNode.innerText = node.firstChild.nodeValue; // ie
lastNode = msgNode;
}

Im Wesentlichen wird also das gelieferte XML-Dokument per XML-DOM ausgelesen, und die darin enthaltenen Werte werden dann in die DOM-Elemente des HTML-Dokumentes eingetragen. Bei Bedarf werden diese Elemente dazu erst einmal erzeugt.

Probleme und Lösungen

Wie man sieht, lassen sich mit AJAX stark interaktive Webseiten sehr einfach programmieren. Es gibt aber auch eine ganze Menge an Problemen über die man sich als Entwickler bewusst sein sollte - auch, wenn diese in der Beispielimplementierung nicht auf den ersten Blick klar werden.

Das erste „A“ in Ajax steht für „asynchron“ – und in der Praxis bedeutet dies, dass man mit multiplen, gleichzeitig ablaufenden Skripten und daraus entstehenden Synchronisationsproblemen klar kommen muss. Die Programmierung mit multiplen Threads ist aber nicht jedermanns Sache – in der Praxis werden die allermeisten Programmierer multiple Threads aus guten Gründen vermeiden.

Ein anderes Problem mit AJAX ist die Tatsache, dass daraus resultierende Websites von Suchmaschinen nicht besonders gut indiziert werden können. Genauer: Nur die nicht interaktiven Elemente, also die, die ohne den Gebrauch von JavaScript und dem DOM dargestellt werden, sind für die Roboter der Suchmaschinen sichtbar. Webseitenbetreiber die ein Interesse daran haben, dass ihre Seiten indiziert werden und dennoch AJAX verwenden möchten, kommen also nicht daran vorbei, eine zweite, nicht AJAX-basierte Version der Seite zur Verfügung zu stellen.

Fazit

Trotz der oben genannten Probleme wird Ajax ein immer beliebteres Mittel um Web-Seiten interaktiver zu gestalten. Bestes Beispiel sind die letzten vorgestellten Programme von Google, etwa der Calendar oder das Notebook. Auch der Einsatz in einem Webforum macht Sinn - können Inhalte doch dem Anwender ohne Reload präsentiert werden. Einige interessante Projekte sind beispielsweise Blursofts MetaForums, bbPress oder das k4 Bulletin Board.

Mit Ajax lassen sich Websites leichter und intuitiver nutzen, teilweise kann man kaum einen Unterschied zu installierten Desktop-Anwendungen ausmachen. Diesen Trend greifen auch andere Internetfirmen auf, so haben sich beispielsweise Yahoo und Map24 ein neues Design inklusive Ajax gegönnt. (mja)