Вы только что наткнулись на эту неожиданную медиа-ошибку в консоли JavaScript DevTools Chrome?
или
Тогда вы находитесь в правильном месте. Не бойтесь. Я объясню , что является причиной этого и как это исправить .
Что является причиной этого
Ниже приведен код JavaScript, который воспроизводит ошибку «Uncaught (in Promise)», которую вы видите:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
Приведенный выше код приводит к появлению этого сообщения об ошибке в Chrome DevTools:
_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
Поскольку видео не загружается из-за preload="none"
, воспроизведение видео не обязательно начинается сразу после выполнения video.play()
.
Более того, начиная с Chrome 50 , вызов play()
элемента <video>
или <audio>
возвращает Promise — функцию, которая асинхронно возвращает один результат. Если воспроизведение прошло успешно, обещание выполняется и одновременно запускается событие playing
. Если воспроизведение завершается неудачей, обещание отклоняется вместе с сообщением об ошибке, объясняющим сбой.
Теперь вот что происходит:
-
video.play()
начинает асинхронную загрузку видеоконтента. -
video.pause()
прерывает загрузку видео, поскольку оно еще не готово. -
video.play()
громко отклоняет асинхронно.
Поскольку в нашем коде мы не обрабатываем обещание воспроизведения видео, в Chrome DevTools появляется сообщение об ошибке.
Как это исправить
Теперь, когда мы понимаем основную причину, давайте посмотрим, что мы можем сделать, чтобы это исправить.
Во-первых, никогда не предполагайте, что какой-либо медиа-элемент (видео или аудио) будет воспроизводиться. Посмотрите на обещание, возвращаемое функцией play
, чтобы узнать, было ли оно отклонено. Стоит отметить, что обещание не будет выполнено до тех пор, пока воспроизведение не начнется, а это означает, что код внутри then()
не будет выполняться до тех пор, пока не начнется воспроизведение мультимедиа.
Пример: автозапуск
<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>
Пример: Воспроизведение и пауза
<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>
Это отлично подходит для этого простого примера, но что, если вы используете video.play()
чтобы иметь возможность воспроизвести видео позже?
Я открою тебе секрет. Вам не обязательно использовать video.play()
, вы можете использовать video.load()
, и вот как:
Пример: выбор и воспроизведение
<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>
Играйте, обещайте поддержку
На момент написания HTMLMediaElement.play()
возвращает обещание в Chrome , Edge, Firefox, Opera и Safari .
Опасная зона
<source>
внутри <video>
заставляет обещание play()
никогда не отклоняться
Для <video src="not-existing-video.mp4"\>
обещание play()
отклоняется, как и ожидалось, поскольку видео не существует. Для <video><source src="not-existing-video.mp4" type='video/mp4'></video>
обещание play()
никогда не отклоняется. Это происходит только в том случае, если нет достоверных источников.