DOMWyjątki - Żądanie play() zostało przerwane

François Beaufort
François Beaufort

Właśnie natknąłem się na ten nieoczekiwany błąd multimediów w Narzędziach deweloperskich w Chrome? konsolę JavaScript?

lub

Jesteś we właściwym miejscu. Bez obaw. Wyjaśnię, co powoduje ten problem i jak to naprawić.

Co to powoduje

Oto fragment kodu JavaScript, który odtwarza komunikat „Nieprzechwycony (obiecany)” poniżej który widzisz:

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

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

Powyższy kod powoduje wyświetlenie tego komunikatu o błędzie w Narzędziach deweloperskich w Chrome:

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

Film nie jest wczytywany z powodu: preload="none", dlatego odtwarzanie nie jest możliwe musi rozpoczynać się natychmiast po wykonaniu video.play().

Dodatkowo od Chrome 50 wywołanie play() na <video> lub <audio> element zwraca Promise, funkcję, która zwraca pojedynczy wynik. asynchronicznie. Jeśli odtworzenie się powiedzie, obietnica zostanie spełniona, a Jednocześnie wywoływane jest zdarzenie playing. Jeśli odtwarzanie się nie uda, obietnica jest odrzucono wraz z komunikatem o błędzie z wyjaśnieniem błędu.

Oto co się teraz dzieje:

  1. video.play() rozpoczyna asynchroniczne wczytywanie treści wideo.
  2. Komponent video.pause() przerywa wczytywanie filmu, ponieważ nie jest jeszcze gotowy.
  3. Funkcja video.play() odrzuca asynchronicznie głośno.

Ponieważ w naszym kodzie nie obsługujemy obietnicy odtwarzania filmu, pojawia się komunikat o błędzie pojawi się w Narzędziach deweloperskich w Chrome.

Jak to naprawić

Znasz już główną przyczynę problemu, więc teraz sprawdźmy, jak go naprawić.

Po pierwsze nie zakładaj, że będą odtwarzane elementy multimedialne (wideo lub dźwięk). Spójrz na obietnica zwrócona przez funkcję play, by sprawdzić, czy została odrzucona. Jest Warto zauważyć, że obietnica nie zostanie zrealizowana, dopóki odtwarzanie co oznacza, że kod w elemencie then() nie będzie wykonywany, dopóki nie gra.

Tak

Przykład: autoodtwarzanie

<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>
Tak

Przykład: Odtwórz i Pauza

<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>

To świetny przykład w tym prostym przykładzie, ale co, jeśli użyjesz funkcji video.play(), aby odtworzyć film później?

Zdradę Ci sekret. Nie musisz używać video.play(), możesz używać usługi video.load(). Aby to zrobić:

Tak

Przykład: Pobierz i Odtwórz

<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>

Zespół Google Play ds. obietnic

W momencie pisania tekstu HTMLMediaElement.play() zwraca obietnicę w języku: Chrome, Edge, Firefox, Opera i Safari.

Strefa zagrożenia

Pole <source> w obrębie <video> sprawia, że obietnica play() nigdy nie odrzuca

W przypadku <video src="not-existing-video.mp4"\> obietnica play() odrzuca jako ponieważ film nie istnieje. W przypadku <video><source src="not-existing-video.mp4" type='video/mp4'></video> obietnica play() nigdy nie odrzuca. Dzieje się tak tylko wtedy, gdy nie ma żadnych prawidłowych źródeł.

Błąd Chromium