Start · Sprachen · JavaScript · Referenz · HTMLMediaElement: canplaythrough

HTMLMediaElement: canplaythrough

Ereignis

Wird ausgelöst, wenn der Browser schätzt, dass das Medium ohne weitere Pufferpausen bis zum Ende abgespielt werden kann.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

element.addEventListener("canplaythrough", handler)

Beschreibung

Das Event canplaythrough wird an einem <audio>- oder <video>-Element ausgelöst, wenn der Browser das Medium abspielen kann und schätzt, dass bei der aktuellen Download-Geschwindigkeit genug Daten vorliegen, um es bis zum Ende ohne Unterbrechung zum Puffern abzuspielen. Zu diesem Zeitpunkt erreicht readyState den Wert HAVE_ENOUGH_DATA (4).

Das Event ist nicht abbrechbar und steigt nicht auf (kein Bubbling). Sie registrieren es entweder mit addEventListener("canplaythrough", handler) oder über die Eigenschaft oncanplaythrough. Der Handler erhält ein einfaches Event-Objekt.

Typische Anwendungen: einen Ladeindikator ausblenden, einen „Abspielen“-Button aktivieren, ein Hintergrundvideo erst dann einblenden, wenn es flüssig läuft, oder Soundeffekte in Spielen vorladen. Die Reihenfolge der Lade-Events ist in der Regel loadstart → durationchange → loadedmetadata → loadeddata → canplay → canplaythrough.

Beachten Sie, dass es sich nur um eine Schätzung handelt: Sinkt die Bandbreite, kann das Medium trotzdem stocken (waiting-Event). Außerdem kann canplaythrough mehrfach feuern, etwa nach einem Sprung mit currentTime oder nach erneutem Puffern.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Eventname "canplaythrough".
$handler Pflicht (event: Event) => void Callback, der beim Auslösen aufgerufen wird. Erhält ein generisches Event-Objekt.
$options boolean | AddEventListenerOptions false Optionen wie { once: true }, um den Listener nach dem ersten Auslösen automatisch zu entfernen.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück; der Handler erhält ein Event-Objekt ohne zusätzliche Eigenschaften.

Beispiele

Ladeindikator ausblenden, sobald das Video flüssig läuft

const video = document.querySelector('#intro');
const spinner = document.querySelector('#spinner');

video.addEventListener('canplaythrough', () => {
  spinner.hidden = true;
  console.log('Bereit, readyState =', video.readyState);
}, { once: true });
Bereit, readyState = 4

Über die on-Property und Entfernen des Listeners

const audio = new Audio('/sounds/theme.mp3');

const onReady = () => {
  console.log('Musik kann ohne Unterbrechung laufen');
  audio.removeEventListener('canplaythrough', onReady);
};
audio.addEventListener('canplaythrough', onReady);

// Alternative per Property (überschreibt frühere Zuweisungen):
// audio.oncanplaythrough = onReady;
// audio.oncanplaythrough = null; // entfernen
Musik kann ohne Unterbrechung laufen

Mehrere Soundeffekte vorladen (Promise-basiert)

const preload = (src) => new Promise((resolve, reject) => {
  const audio = new Audio();
  audio.preload = 'auto';
  audio.addEventListener('canplaythrough', () => resolve(audio), { once: true });
  audio.addEventListener('error', () => reject(new Error(`Fehler: ${src}`)), { once: true });
  audio.src = src;
  // Falls schon gepuffert (z. B. aus dem Cache):
  if (audio.readyState >= HTMLMediaElement.HAVE_ENOUGH_DATA) resolve(audio);
});

const sounds = await Promise.all(['/sfx/jump.wav', '/sfx/coin.wav'].map(preload));
console.log(`${sounds.length} Sounds geladen`);
2 Sounds geladen

// Wichtig · Fallstricke

  • Nur eine Schätzung: Trotz canplaythrough kann die Wiedergabe bei schwankender Bandbreite stocken. Behandeln Sie zusätzlich waiting und stalled.
  • Mehrfaches Auslösen: Nach Sprüngen (seeking) oder erneutem Puffern kann das Event erneut feuern. Nutzen Sie { once: true }, wenn Sie nur die erste Bereitschaft interessiert.
  • Listener zu spät registriert: Ist das Medium bereits gepuffert (Cache), ist das Event schon vorbei. Prüfen Sie vorher readyState >= 4.
  • preload-Attribut: Bei preload="none" oder "metadata" und auf vielen Mobilgeräten (vor allem iOS Safari) wird ohne Benutzerinteraktion nicht genug geladen – canplaythrough feuert dann erst nach play() oder gar nicht vorab.
  • Kein Bubbling: Ein Listener am Elternelement fängt das Event nur in der Capture-Phase ab (addEventListener(..., true)).
  • Kompatibilität: von allen modernen Browsern unterstützt.