Signatur
Beschreibung
Der Konstruktor new XMLHttpRequest() erzeugt ein neues, noch nicht konfiguriertes Anfrageobjekt. Sein readyState ist dann 0 (UNSENT). Erst mit open(method, url) legst du Methode und Ziel fest, danach kannst du Header setzen (setRequestHeader()) und die Anfrage mit send(body) abschicken.
XMLHttpRequest (XHR) ist die klassische Grundlage von AJAX. Trotz des Namens kann es beliebige Daten übertragen, also JSON, Text, Blob, ArrayBuffer, FormData oder ein Document. Welches Format die Antwort hat, bestimmst du über responseType.
Für neuen Code ist meist die Promise-basierte Fetch-API die bessere Wahl. XHR ist aber weiterhin sinnvoll, wenn du den Upload-Fortschritt über xhr.upload.onprogress brauchst, denn das kann fetch() bis heute nicht direkt. Außerdem begegnet dir XHR häufig in älterem Code und in Bibliotheken.
Jedes Objekt ist für genau eine Anfrage gedacht. Ein erneuter Aufruf von open() bricht eine laufende Anfrage ab. Für parallele Anfragen erzeugst du deshalb jeweils ein eigenes Objekt.
Rückgabewert
XMLHttpRequest-Objekt mit readyState === 0 (UNSENT).Beispiele
JSON per GET laden
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
xhr.responseType = 'json';
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
console.log('Titel:', xhr.response.title);
} else {
console.error('HTTP-Fehler:', xhr.status);
}
});
xhr.addEventListener('error', () => console.error('Netzwerkfehler'));
xhr.send();
XHR in ein Promise verpacken (mit Timeout)
const request = (method, url, body = null) =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.timeout = 5000; // 5 Sekunden
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'json';
xhr.onload = () =>
xhr.status < 400 ? resolve(xhr.response) : reject(new Error(`Status ${xhr.status}`));
xhr.onerror = () => reject(new Error('Netzwerkfehler'));
xhr.ontimeout = () => reject(new Error('Zeitüberschreitung'));
xhr.send(body ? JSON.stringify(body) : null);
});
const main = async () => {
const post = await request('POST', 'https://jsonplaceholder.typicode.com/posts', { title: 'Hallo' });
console.log('Neue ID:', post.id);
};
main();
Datei-Upload mit Fortschrittsanzeige
// HTML: <input type="file" id="datei"> <progress id="balken" max="100" value="0"></progress>
const input = document.querySelector('#datei');
const balken = document.querySelector('#balken');
input.addEventListener('change', () => {
const formData = new FormData();
formData.append('upload', input.files[0]);
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
balken.value = Math.round((event.loaded / event.total) * 100);
}
});
xhr.addEventListener('load', () => console.log('Upload fertig:', xhr.status));
xhr.open('POST', '/api/upload');
xhr.send(formData); // Content-Type setzt der Browser automatisch
});
// Wichtig · Fallstricke
- Kein
new, kein Objekt: Ruft manXMLHttpRequest()ohnenewauf, wirft das einenTypeError. - HTTP-Fehler lösen kein
erroraus: Auch bei 404 oder 500 feuertload. Prüfe deshalb immerxhr.status. Das Ereigniserrorkommt nur bei Netzwerk- oder CORS-Fehlern. - Synchrone Anfragen vermeiden:
open(method, url, false)blockiert den Hauptthread und gilt dort als veraltet. Browser geben dann Warnungen aus, außerdem funktionierentimeoutundresponseTypein diesem Modus nicht. - Reihenfolge beachten:
setRequestHeader()geht nur nachopen()und vorsend(), sonst gibt es einenInvalidStateError. - CORS: Anfragen an andere Ursprünge funktionieren nur, wenn der Server die passenden
Access-Control-Allow-*-Header schickt. Cookies werden nur mitxhr.withCredentials = truemitgesendet. - Sicherheit: Füge Antwortdaten nie ungeprüft per
innerHTMLin die Seite ein, sonst droht XSS. Nutze stattdessentextContentoder bereinige die Daten vorher. Die Content Security Policy (connect-src) kann XHR-Ziele einschränken. - Kompatibilität: Wird von allen Browsern und in Web Workern unterstützt, aber nicht in Service Workern (dort nur
fetch()). Node.js hat XHR nicht eingebaut.