Signatur
Beschreibung
XMLHttpRequestEventTarget ist ein abstraktes Interface: Man erzeugt es nie direkt. Es erbt von EventTarget und legt die Ereignis-Handler fest, die sowohl XMLHttpRequest (Download bzw. die gesamte Anfrage) als auch XMLHttpRequestUpload (erreichbar über xhr.upload) teilen. So lässt sich der Fortschritt beim Hoch- und Herunterladen mit demselben Satz Handler verfolgen.
Folgende Handler-Eigenschaften sind definiert. Jeder bekommt ein ProgressEvent übergeben:
onloadstart– die Übertragung beginnt.onprogress– wird während der Übertragung regelmäßig ausgelöst (loaded,total,lengthComputable).onabort– die Anfrage wurde mitabort()abgebrochen.onerror– ein Netzwerkfehler ist aufgetreten (z. B. bei CORS-Ablehnung oder fehlender Verbindung).onload– die Übertragung ist erfolgreich abgeschlossen (auch bei HTTP-Status 404 oder 500!).ontimeout– das inxhr.timeoutgesetzte Zeitlimit wurde überschritten.onloadend– die Übertragung ist beendet, egal ob erfolgreich oder nicht (nachload,error,abortodertimeout).
Statt der on…-Eigenschaften kann man gleichwertig addEventListener("progress", handler) usw. verwenden – das erlaubt mehrere Listener und das gezielte Entfernen mit removeEventListener. Typischer Einsatzzweck ist heute vor allem die Upload-Fortschrittsanzeige, weil fetch() dafür keine einfache Entsprechung bietet.
Rückgabewert
XMLHttpRequest bzw. xhr.upload (XMLHttpRequestUpload) genutzt.Beispiele
Instanz erhalten und Vererbung prüfen
const xhr = new XMLHttpRequest();
// Beide Objekte implementieren XMLHttpRequestEventTarget
console.log(xhr instanceof XMLHttpRequestEventTarget); // true
console.log(xhr.upload instanceof XMLHttpRequestEventTarget); // true
console.log(xhr instanceof EventTarget); // true
// Direkte Instanziierung ist nicht erlaubt
try {
new XMLHttpRequestEventTarget();
} catch (err) {
console.log(err.name);
}
Download mit Fortschritt, Fehler- und Timeout-Behandlung
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/berichte.json');
xhr.responseType = 'json';
xhr.timeout = 10000;
xhr.onloadstart = () => console.log('Download startet');
xhr.onprogress = (e) => {
if (e.lengthComputable) {
console.log(`Fortschritt: ${Math.round((e.loaded / e.total) * 100)} %`);
}
};
xhr.onload = () => {
// load feuert auch bei 404/500 – Status prüfen!
if (xhr.status >= 200 && xhr.status < 300) {
console.log('Daten:', xhr.response);
} else {
console.warn('HTTP-Fehler', xhr.status);
}
};
xhr.onerror = () => console.error('Netzwerkfehler');
xhr.ontimeout = () => console.error('Zeitlimit überschritten');
xhr.onloadend = () => console.log('Anfrage beendet');
xhr.send();
Upload-Fortschritt mit addEventListener / removeEventListener
const input = document.querySelector('#datei');
const balken = document.querySelector('progress');
const hochladen = (datei) => {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append('datei', datei);
const onProgress = (e) => {
if (e.lengthComputable) {
balken.max = e.total;
balken.value = e.loaded;
}
};
// Listener am Upload-Objekt (XMLHttpRequestUpload) VOR send() registrieren
xhr.upload.addEventListener('progress', onProgress);
xhr.upload.addEventListener('loadend', () => {
xhr.upload.removeEventListener('progress', onProgress);
console.log('Upload abgeschlossen');
}, { once: true });
xhr.open('POST', '/upload');
xhr.send(formData);
};
input.addEventListener('change', () => {
if (input.files.length) hochladen(input.files[0]);
});
Promise-Wrapper mit Abbruch
const ladeText = (url, signal) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.addEventListener('load', () => resolve(xhr.responseText));
xhr.addEventListener('error', () => reject(new Error('Netzwerkfehler')));
xhr.addEventListener('abort', () => reject(new DOMException('Abgebrochen', 'AbortError')));
signal?.addEventListener('abort', () => xhr.abort());
xhr.send();
});
const controller = new AbortController();
ladeText('/langsam.txt', controller.signal).catch((e) => console.log(e.name));
controller.abort();
// Wichtig · Fallstricke
load≠ Erfolg:onloadwird auch bei HTTP-Fehlercodes (404, 500) ausgelöst.onerrorfeuert nur bei Netzwerk- oder CORS-Fehlern. Immerxhr.statusprüfen.- Upload-Listener vor
send()registrieren: Listener aufxhr.upload, die erst nachsend()angehängt werden, erfassen möglicherweise keine Ereignisse. Außerdem löst das Registrieren von Upload-Listenern bei Cross-Origin-Anfragen einen CORS-Preflight (OPTIONS) aus. lengthComputable: Istfalse, wenn der Server keinenContent-Length-Header sendet (oder die Antwort komprimiert/chunked ist). Dann isttotalgleich0.- Reihenfolge:
loadstart→progress* → genau eines vonload/error/abort/timeout→loadend. Aufräumarbeiten gehören deshalb nachloadend. readystatechangegehört nicht zu diesem Interface, sondern nur zuXMLHttpRequest.- Kompatibilität: in allen modernen Browsern verfügbar, auch in Web Workern. In Service Workern gibt es kein
XMLHttpRequest– dortfetch()verwenden. Für neuen Code ohne Upload-Fortschritt istfetch()in der Regel die bessere Wahl.