Signatur
Beschreibung
ProgressEvent.loaded ist eine schreibgeschützte Eigenschaft eines ProgressEvent. Sie gibt an, wie viel von einem laufenden Vorgang schon erledigt ist. Bei HTTP-Übertragungen über XMLHttpRequest sind das die bisher übertragenen Bytes. Beim Lesen mit FileReader sind es die bereits gelesenen Bytes.
Zusammen mit ProgressEvent.total und ProgressEvent.lengthComputable lässt sich daraus ein Fortschritt in Prozent berechnen, etwa für Fortschrittsbalken bei Datei-Uploads, großen Downloads oder beim Einlesen lokaler Dateien. Ist die Gesamtgröße unbekannt (lengthComputable === false), zeigt loaded nur die absolute Menge an. Dann eignet sich eher eine Anzeige wie „2,3 MB geladen“.
Beim Herunterladen zählt loaded die Bytes des Antwort-Rumpfs, wie sie übertragen werden. Bei komprimierten Antworten (z. B. Content-Encoding: gzip) ist das die komprimierte Größe. Für Uploads meldet man sich an den Events von xhr.upload an, nicht an denen von xhr selbst.
Rückgabewert
0.Beispiele
Download-Fortschritt mit XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', '/dateien/video.mp4');
xhr.responseType = 'blob';
xhr.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const prozent = Math.round((event.loaded / event.total) * 100);
console.log(`Geladen: ${prozent} %`);
} else {
console.log(`Geladen: ${(event.loaded / 1024).toFixed(1)} KB`);
}
});
xhr.addEventListener('load', () => console.log('Download fertig'));
xhr.send();
Upload-Fortschritt in einem <progress>-Element anzeigen
const input = document.querySelector('#datei');
const balken = document.querySelector('progress');
input.addEventListener('change', () => {
const formData = new FormData();
formData.append('datei', input.files[0]);
const xhr = new XMLHttpRequest();
// Upload-Events hängen an xhr.upload!
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
balken.max = event.total;
balken.value = event.loaded;
}
};
xhr.upload.onload = () => console.log('Upload abgeschlossen');
xhr.open('POST', '/api/upload');
xhr.send(formData);
});
Lokale Datei mit FileReader einlesen
const leseDatei = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onprogress = (event) => {
console.log(`${event.loaded} von ${event.total} Bytes gelesen`);
};
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(reader.error);
reader.readAsArrayBuffer(file);
});
document.querySelector('#datei').addEventListener('change', async (e) => {
const buffer = await leseDatei(e.target.files[0]);
console.log('Fertig:', buffer.byteLength, 'Bytes');
});
Eigenes ProgressEvent erzeugen
const event = new ProgressEvent('progress', {
lengthComputable: true,
loaded: 250,
total: 1000
});
console.log(event.loaded / event.total);
event.loaded = 999; // wird ignoriert, schreibgeschützt
console.log(event.loaded);
// Wichtig · Fallstricke
- Vor dem Teilen immer
lengthComputableprüfen: Ist die Gesamtgröße unbekannt (z. B. keinContent-Length-Header oder Chunked-Transfer), isttotalgleich0.loaded / totalergibt dannInfinityoderNaN. - Komprimierte Antworten:
loadedzählt die übertragenen, also komprimierten Bytes. Die Größe der entpackten Antwort kann deutlich größer sein. - Upload und Download sind getrennt: Den Upload-Fortschritt melden nur die Events von
xhr.upload. Handler dafür müssen vorsend()registriert werden. Außerdem können sie bei CORS einen Preflight auslösen. - Schreibgeschützt: Zuweisungen werden stillschweigend ignoriert (im Strict Mode gibt es einen
TypeError). Eigene Werte setzt man über den Konstruktornew ProgressEvent(). - Häufigkeit: Browser feuern
progressetwa alle 50 ms. Aufwendige DOM-Aktualisierungen sollte man trotzdem sparsam halten, z. B. mitrequestAnimationFrame. - Fetch-API:
fetch()erzeugt keineProgressEvents. Den Fortschritt misst man dort selbst, indem manresponse.body.getReader()ausliest und die Byte-Anzahlen der Blöcke aufsummiert. - Die Eigenschaft wird von allen modernen Browsern unterstützt und ist auch in Web Workern verfügbar.