Start · Sprachen · JavaScript · Referenz · XMLHttpRequestEventTarget: load

XMLHttpRequestEventTarget: load

Ereignis

Das <code>load</code>-Ereignis wird ausgelöst, wenn eine <code>XMLHttpRequest</code>-Transaktion erfolgreich abgeschlossen wurde, also eine Antwort vollständig empfangen ist.

seit JavaScript Baseline: alle Browser (XMLHttpRequest Level 2) Kategorie: webapi

Signatur

xhr.addEventListener("load", handler) / xhr.onload = handler

Beschreibung

Das load-Ereignis gehört zum Interface XMLHttpRequestEventTarget und tritt sowohl bei XMLHttpRequest-Objekten als auch bei deren upload-Objekt (XMLHttpRequestUpload) auf. Beim Anfrageobjekt bedeutet es: Die Antwort wurde vollständig empfangen. Beim upload-Objekt bedeutet es: Der Anfragekörper wurde vollständig an den Server übertragen.

Wichtig: „Erfolgreich“ bezieht sich nur auf die Übertragung, nicht auf den HTTP-Status. Auch Antworten mit 404 oder 500 lösen load aus. Netzwerkfehler, CORS-Blockaden, Abbrüche und Zeitüberschreitungen lösen stattdessen error, abort bzw. timeout aus. Deshalb sollte man im Handler immer xhr.status prüfen.

Das Ereignis ist ein ProgressEvent mit den Eigenschaften loaded, total und lengthComputable. Es wird nach readystatechange mit readyState === 4 und vor loadend ausgelöst. Es ist nicht abbrechbar (not cancelable) und steigt nicht auf (bubbelt nicht).

Registrieren lässt sich der Handler per addEventListener("load", handler) (mehrere Listener möglich, per removeEventListener entfernbar) oder über die Eigenschaft onload (nur ein Handler, wird bei erneuter Zuweisung überschrieben).

Rückgabewert

Typ
void
Beschreibung
Weder addEventListener noch die Zuweisung an onload liefern einen verwertbaren Rückgabewert. Der Handler erhält ein ProgressEvent.

Beispiele

JSON laden mit addEventListener und Statusprüfung

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
xhr.responseType = 'json';

xhr.addEventListener('load', () => {
  // load feuert auch bei 404/500 – daher Status prüfen
  if (xhr.status >= 200 && xhr.status < 300) {
    console.log('Titel:', xhr.response.title);
  } else {
    console.warn('HTTP-Fehler:', xhr.status);
  }
});

xhr.addEventListener('error', () => console.error('Netzwerkfehler'));
xhr.send();
Titel: delectus aut autem

onload-Property und Listener wieder entfernen

const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/status');

// Variante 1: onload (nur ein Handler möglich)
xhr.onload = (event) => {
  console.log(`Geladen: ${event.loaded} Bytes, Status ${xhr.status}`);
};

// Variante 2: benannter Listener, der sich selbst wieder entfernt
const onLoad = () => {
  console.log('Einmaliger Listener');
  xhr.removeEventListener('load', onLoad);
};
xhr.addEventListener('load', onLoad);

xhr.send();
Geladen: 42 Bytes, Status 200 Einmaliger Listener

Upload-Fertigstellung über xhr.upload

const input = document.querySelector('input[type=file]');

input.addEventListener('change', () => {
  const formData = new FormData();
  formData.append('datei', input.files[0]);

  const xhr = new XMLHttpRequest();
  xhr.upload.addEventListener('progress', (e) => {
    if (e.lengthComputable) {
      console.log(`Upload: ${Math.round((e.loaded / e.total) * 100)} %`);
    }
  });
  // Körper vollständig gesendet (Serverantwort steht noch aus)
  xhr.upload.addEventListener('load', () => console.log('Upload übertragen'));
  // Antwort vollständig empfangen
  xhr.addEventListener('load', () => console.log('Server-Antwort:', xhr.status));

  xhr.open('POST', '/upload');
  xhr.send(formData);
});
Upload: 50 % Upload: 100 % Upload übertragen Server-Antwort: 201

XHR in ein Promise verpacken

const request = (method, url) => new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open(method, url);
  xhr.onload = () => (xhr.status >= 200 && xhr.status < 300)
    ? resolve(xhr.responseText)
    : reject(new Error(`HTTP ${xhr.status}`));
  xhr.onerror = () => reject(new Error('Netzwerkfehler'));
  xhr.ontimeout = () => reject(new Error('Zeitüberschreitung'));
  xhr.timeout = 5000;
  xhr.send();
});

const main = async () => {
  try {
    const text = await request('GET', '/hallo.txt');
    console.log(text);
  } catch (err) {
    console.error(err.message);
  }
};
main();
Hallo Welt

// Wichtig · Fallstricke

  • Kein HTTP-Erfolgsindikator: load wird auch bei Statuscodes wie 404 oder 500 ausgelöst. Immer xhr.status prüfen.
  • CORS- und Netzwerkfehler lösen error statt load aus; dabei ist xhr.status gleich 0. Aufräumarbeiten, die in jedem Fall laufen sollen, gehören in loadend.
  • Upload-Listener vor send() registrieren: Listener auf xhr.upload müssen vor dem Aufruf von send() gesetzt werden. Sie können außerdem einen CORS-Preflight erzwingen.
  • Reihenfolge: readystatechange (readyState 4) → load → loadend.
  • onload erlaubt nur einen Handler; eine erneute Zuweisung überschreibt den vorherigen. Für mehrere Handler addEventListener verwenden.
  • Bei synchronen Anfragen (open(..., false)) werden Ereignisse im Hauptthread blockierend verarbeitet; synchrones XHR ist veraltet und sollte gemieden werden.
  • Kompatibilität: In allen modernen Browsern und ab IE10 verfügbar. Für neuen Code ist die fetch()-API meist die bessere Wahl; XHR bleibt aber nützlich, wenn man den Upload-Fortschritt verfolgen will.