DOMException - Het play()-verzoek is onderbroken

François Beaufort
François Beaufort

Ben je zojuist deze onverwachte mediafout tegengekomen in de Chrome DevTools JavaScript Console?

of

Dan bent u op de juiste plek. Heb geen angst. Ik zal uitleggen waardoor dit wordt veroorzaakt en hoe u dit kunt oplossen .

Wat veroorzaakt dit

Hier is wat JavaScript-code hieronder die de fout 'Niet opgevangen (in belofte)' reproduceert die u ziet:

Niet doen
<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  video.play(); // <-- This is asynchronous!
  video.pause();
</script>

De bovenstaande code resulteert in dit foutbericht in Chrome DevTools:

_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

Omdat de video niet wordt geladen vanwege preload="none" , begint het afspelen van de video niet noodzakelijkerwijs onmiddellijk nadat video.play() is uitgevoerd.

Bovendien retourneert een play() aanroep op een a <video> of <audio> -element sinds Chrome 50 een Promise , een functie die asynchroon één enkel resultaat retourneert. Als het afspelen slaagt, wordt de belofte vervuld en wordt tegelijkertijd de playing geactiveerd. Als het afspelen mislukt, wordt de belofte afgewezen, samen met een foutmelding waarin de fout wordt uitgelegd.

Dit is wat er nu gebeurt:

  1. video.play() begint asynchroon video-inhoud te laden.
  2. video.pause() onderbreekt het laden van de video omdat deze nog niet klaar is.
  3. video.play() wijst asynchroon luid af.

Omdat we de videoplay Promise niet verwerken in onze code, verschijnt er een foutmelding in Chrome DevTools.

Hoe het te repareren

Nu we de oorzaak begrijpen, gaan we kijken wat we kunnen doen om dit op te lossen.

Ten eerste: ga er nooit van uit dat een media-element (video of audio) wordt afgespeeld. Kijk naar de belofte die door de play wordt geretourneerd om te zien of deze is afgewezen. Het is de moeite waard om op te merken dat de belofte pas zal worden vervuld als het afspelen daadwerkelijk is begonnen, wat betekent dat de code in then() pas wordt uitgevoerd als de media wordt afgespeeld.

Doen

Voorbeeld: automatisch afspelen

<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  // Show loading animation.
  var playPromise = video.play();

  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>
Doen

Voorbeeld: Afspelen en pauzeren

<video id="video" preload="none" src="https://example.com/file.mp4"></video>
 
<script>
  // Show loading animation.
  var playPromise = video.play();
 
  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
      // We can now safely pause video...
      video.pause();
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>

Dat is geweldig voor dit eenvoudige voorbeeld, maar wat als je video.play() gebruikt om een ​​video later af te spelen?

Ik zal je een geheim vertellen. Je hoeft video.play() niet te gebruiken, je kunt video.load() gebruiken en zo doe je het:

Doen

Voorbeeld: ophalen en afspelen

<video id="video"></video>
<button id="button"></button>

<script>
  button.addEventListener('click', onButtonClick);

  function onButtonClick() {
    // This will allow us to play video later...
    video.load();
    fetchVideoAndPlay();
  }

  function fetchVideoAndPlay() {
    fetch('https://example.com/file.mp4')
    .then(response => response.blob())
    .then(blob => {
      video.srcObject = blob;
      return video.play();
    })
    .then(_ => {
      // Video playback started ;)
    })
    .catch(e => {
      // Video playback failed ;(
    })
  }
</script>

Speel belofte-ondersteuning

Op het moment van schrijven retourneert HTMLMediaElement.play() een belofte in Chrome , Edge, Firefox, Opera en Safari .

Gevarenzone

<source> binnen <video> zorgt ervoor dat play() de belofte nooit afwijst

Voor <video src="not-existing-video.mp4"\> wordt de belofte play() afgewezen, zoals verwacht, omdat de video niet bestaat. Voor <video><source src="not-existing-video.mp4" type='video/mp4'></video> wordt de belofte play() nooit afgewezen. Het gebeurt alleen als er geen geldige bronnen zijn.

Chroombug