Signatur
Beschreibung
ProgressEvent erbt von Event und beschreibt, wie weit ein länger laufender Vorgang schon ist. Ausgelöst wird es unter anderem von XMLHttpRequest, XMLHttpRequestUpload (über xhr.upload) und FileReader. Die Ereignistypen sind loadstart, progress, load, error, abort, timeout und loadend.
Zusätzlich zu den Eigenschaften von Event gibt es drei schreibgeschützte Eigenschaften:
lengthComputable(boolean):true, wenn die Gesamtgröße bekannt ist, z. B. über den HeaderContent-Length.loaded(number): Bytes, die bereits übertragen oder verarbeitet wurden.total(number): Gesamtgröße in Bytes. Ist sie unbekannt, ist der Wert0.
Typischer Einsatz sind Fortschrittsbalken für Datei-Uploads, große Downloads oder das Einlesen lokaler Dateien. Mit dem Konstruktor new ProgressEvent(type, init) kann man solche Ereignisse auch selbst erzeugen, etwa für Tests oder eigene Lade-Komponenten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses (Konstruktor-Parameter), z. B. "progress" oder "load". |
|
| $options | ProgressEventInit | {} | Objekt mit lengthComputable (Standard false), loaded (Standard 0) und total (Standard 0) sowie den EventInit-Feldern bubbles, cancelable und composed. |
Rückgabewert
ProgressEvent-Objekt (beim Konstruktor-Aufruf).Beispiele
Upload-Fortschritt mit XMLHttpRequest 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();
xhr.open('POST', '/api/upload');
// Upload-Fortschritt: Die Listener hängen an xhr.upload, nicht an xhr
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const prozent = Math.round((event.loaded / event.total) * 100);
balken.value = prozent;
console.log(`Upload: ${prozent} %`);
}
});
xhr.addEventListener('loadend', (event) => {
console.log(`Fertig, Status ${xhr.status}, ${event.loaded} Bytes`);
});
xhr.send(formData);
});
Lokale Datei mit FileReader einlesen
const input = document.querySelector('input[type=file]');
input.addEventListener('change', () => {
const reader = new FileReader();
reader.onprogress = (event) => {
if (event.lengthComputable) {
console.log(`Gelesen: ${event.loaded} von ${event.total} Bytes`);
}
};
reader.onload = (event) => {
console.log(event instanceof ProgressEvent); // true
console.log('Zeichen:', reader.result.length);
};
reader.onerror = () => console.error('Fehler:', reader.error);
reader.readAsText(input.files[0]);
});
Eigenes ProgressEvent erzeugen und auslösen
const lader = new EventTarget();
lader.addEventListener('progress', (e) => {
const anteil = e.lengthComputable ? (e.loaded / e.total) * 100 : NaN;
console.log(e.type, e.loaded, e.total, `${anteil} %`);
});
const ereignis = new ProgressEvent('progress', {
lengthComputable: true,
loaded: 30,
total: 120
});
lader.dispatchEvent(ereignis);
// Wichtig · Fallstricke
- Nicht immer bekannte Gesamtgröße: Prüfe vor jeder Division
lengthComputable. Ist esfalse, isttotalgleich0undloaded / totalergibtInfinity. Das passiert, wenn der Server keinContent-Lengthmitschickt, etwa bei Chunked Encoding. - Komprimierung: Bei
gzip/br-Antworten kann sichloadedauf die komprimierten Bytes beziehen, der Wert ist dann je nach Browser nicht genau vergleichbar. - Upload-Listener rechtzeitig setzen: Listener auf
xhr.uploadmüssen vorsend()registriert werden. Außerdem lösen sie bei Cross-Origin-Anfragen einen CORS-Preflight aus. - fetch() hat keine Fortschritts-Ereignisse: Für den Download-Fortschritt liest man
response.body(einReadableStream) und zählt die Bytes selbst. Für den Upload-Fortschritt istXMLHttpRequestweiterhin die verlässliche Lösung. - Häufigkeit:
progresswird etwa alle 50 ms oder seltener ausgelöst. Rechenintensive Aktualisierungen der Oberfläche sollte man drosseln, z. B. mitrequestAnimationFrame. - In Workern gibt es die Schnittstelle ebenfalls. Der Konstruktor wird von allen modernen Browsern unterstützt.