Вы только что наткнулись на эту неожиданную медиа-ошибку в консоли 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()
никогда не отклоняется. Это происходит только в том случае, если нет достоверных источников.