CSS, HTML und Javascript mit {stil}

Javascript XMLHttpRequest und Ajax

XMLHttprequest Grundlagen: XML-Datei vom Server lesen Mit XHR holt Javascript Daten vom Server

Der XMLHttpRequest (kurz XHR) tauscht Daten zwischen Client und Server im Hintergrund aus, ohne die Seite komplett neu zu laden. Diese Technik ist als Ajax (Asynchronous Javascript And XML) bekannt geworden und hat sich 2005 einen Namen gemacht: Das war der Kern von Web 2.0.

Javascript XHR prüft z.B. Formulareingaben gegen die Datenbank ohne Hin- und Her zwischen Client und Server, lädt zusätzliche Informationen – mit und ohne Anwendung auf dem Server.

Bei der klassischen Webanwendung (z.B. bei einem PHP-Skript) lösen Aktionen des Benutzers einen HTTP-Request zurück zum Server aus.

Das PHP-Script verifiziert den Benutzer, liest Daten aus der Datenbank, berechnet ein paar Zahlen und liefert dann eine neue HTML-Seite an den Client aus. Dabei besteht die neue Seite zum größten Teil aus denselben Elementen wie vorher und nur wenige Inhalte wurden tatsächlich geändert.

Über viele Jahre haben Webentwickler nach einer sauberen Technik gerufen, die eine Verbindung zum Server aufrecht erhält, während Transaktionen im Hintergrund laufen und frisch angelieferte Daten in die Seite integriert werden.

Microsoft hatte diese Lücke als Erster mit dem XMLHttpRequest-Objekt geschlossen. Die Mainstream-Browser folgten in Windeseile und das W3C erhob den XMLHttpRequest Level 1 zum Standard.

XMLHttpRequest: XML-Datei laden

XHR ist eine Schnittstelle zwischen Javascript und den Daten auf dem Server. Im einfachsten Fall holt Javascript Daten aus einer XML-Datei vom Server – ohne Beteiligung einer serverseitigen Anwendung.

Ablauf des XMLHttpRequest beim Laden einer XML-Datei Javascript sendet einen Request an den Server und lädt eine XML-Datei
Mit dem XMLHttpRequest sendet ein Javascript z.B. die Anforderung einer Datei an den Server und kann die Daten direkt per DOM und CSS in das Dokument einbinden, ohne die Seite neu zu laden.

Wer jetzt hier glaubt, der XMLHttpRequest sei etwas für XML-Dokumente: Der Name XMLHttpRequest ist irreführend.

  • Zunächst einmal unterstützt der XMLHttpRequest neben XML alle textbasierten Formate.
  • Zweitens kann das Objekt einen Request sowohl über HTTP als auch über HTTPS senden.
  • Am Ende unterstützt der XMLHttpRequest sowohl Requests als auch die Antworten.

Wie der XMLHttpRequest funktioniert

Der XMLHttpRequest öffnet eine Verbindung zu einer URL auf dem Server und sendet einen HTTP-Request über diese Verbindung. Die Daten können in Form einer XML-Datei auf dem Server liegen, als flacher Text oder von einem PHP-Script als Antwort auf einen GET- oder POST-Request des XMLHttpRequests übertragen werden.

?

Das eröffnet Javascript-Anwendungen eine asynchrone Verarbeitung von Daten innerhalb einer persistenten (beständigen) Verbindung anstelle der typischen Stop-and-Go-Komminikation herkömmlicher Anwendungen.

Beispiel: XML-Datei lesen

Auf dem Server liegen Daten in einer XML-Datei (data.xml).

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <buchliste>
   <buch>
     <titel>Das Universum in einer Nussschale</titel>
     <autor>Stephen Hawking</autor>
     <jahr>1980</jahr>
   </buch>
   <buch>
     <titel>Ab die Post!</titel>
     <autor>Terry Pratchet</autor>
     <jahr>2003</jahr>
   </buch>
   …
  </buchliste>
</data>
Im HTML
<button id="xmlrequest" 
        data-xmlrequest="xmlhttp-data.xml"">Datensätze zeigen</button>
Javascript: XMLHTTPRequest auslösen
document.querySelector('#xmlrequest').addEventListener(
    'click', 
    function (evt) {
	    var showXML = processXMLHttpRequest ( 
		    this.dataset.xmlrequest, 
		    this.parentNode
	    );
    }
);

Der Klick auf den Button liest die URL der XML-Datei aus dem data-Attribut (this.dataset.xmlrequest) und übergibt im zweiten Parameter das HTML-Element, in das die Daten geladen werden sollen (this.parentNode).

XHR open() und send()

Die gebräuchlichste Anweisungssequenz für einen XMLHttpRequest besteht aus

  1. dem Erzeugen einer Instanz des XMLHttpRequest-Objekts
  2. Aufruf der open()-Methode
  3. Senden des Requests mit der send()-Methode
  4. Abfragen von onreadystatechange und Aufruf einer Funktion, die beim Eintreffen der Antwort die Verarbeitung übernimmt.
function processXMLHttpRequest(file, location) {
   var xmlObj = new XMLHttpRequest();
   xmlObj.open ('GET', file, true);
   xmlObj.send ('');

   xmlObj.onreadystatechange = function() {
      if(xmlObj.readyState == 'DONE') {
         processXML(xmlObj.responseXML, location);
      }
   }
}

xmlObj.open ('GET', file, true) sendet den GET-Request an den Server.

  • Der erste Parameter der Methode open gibt die Request-Methode an (GET oder POST),
  • der zweite Parameter die URL zum Anwendung auf dem Server.
  • Der dritte Parameter steht für async = true – der Request wird asynchron ausgeführt und blockiert die Seite nicht.

Würde das Script Daten an den Server übertragen, wäre der erste Parameter von xhr.open ein POST, und der Parameter von xhr.send wären die Daten, die an den Server gesendet würden.

xmlObj.send ('') sendet den Request mit dem Parameter null.

XMLHttpRequest.response

Die zurückgegebene Objektreferenz beider Konstruktoren ist ein XMLHttpRequest-Objekt, dessen Methoden alle Operationen steuern und dessen Eigenschaften die Daten, die vom Server zurückgeliefert werden, speichern.

xmlObj.onreadystatechange = function() {
	if(xmlObj.readyState === 4) {
		if (xmlObj.status === 200) {
			console.log ("done 200");
			processXML(xmlObj.responseXML, location);
		} else {
			console.log("Error", xmlObj.statusText);
		}
	}
}

readystatechange ist das Event, dass alle Antworten abfängt. Ursprünglich war readystatechange das einzige Ereignis des XMLHttpRequest, aber mit XMLHttpRequest Version 2 sind weitere Events wie XHR onload und onerror hinzugekommen.

processXML() wird aufgerufen, wenn readyState == 'DONE' ist und parst die Elemente der XML-Datei. Der Einfachheit zuliebe werden die ausgelesenen Daten in einem PRE-Element ausgegeben, das am Ende das .classList-Element mit dem Link ersetzt.

function processXML(obj, location) {
   var rows = obj.getElementsByTagName('buch');
   var listBox = document.createElement('pre');
   var listText = "";
   for (var i=0, row; row=rows[i]; i++) {
      var elems = row.childNodes;
      for (var j=0, srow; srow=elems[j]; j++) {
         if (srow.nodeType == 1) {
            listText += srow.firstChild.data + "   ";
         }
      }
      listText += "\n";
   }
   text = document.createTextNode(listText);
   listBox.appendChild(text);
   location.parentNode.replaceChild(listBox, location, listBox);
}

Prüfen, ob ein Bild oder ein Link existiert


(function(){
	var xhr = new XMLHttpRequest();
    xhr.open('HEAD', "xmlhttp.png", true);
    xhr.send();
     
    if (xhr.status == "404") {
    	console.log ("Gibts nicht");
        return false;
    } else {
    	console.log ("Alles OK xmlhttp.png gibt es");
        return true;
    }
})();
? xmlObj.open ('GET', file, true); xmlObj.send (''); if (xmlObj.status === 200) { processXML(xmlObj.responseXML, location); } < / > XML