Você acabou de encontrar esse erro de mídia inesperado no console JavaScript do Chrome DevTools?
ou
Então você está no lugar certo. Não se preocupe. Vou explicar o que está causando isso e como corrigir.
O que está causando isso?
Confira abaixo um código JavaScript que reproduz o erro "Uncaught (in promise)" que você está recebendo:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
O código acima resulta nesta mensagem de erro no Chrome DevTools:
_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
Como o vídeo não é carregado devido a preload="none", a reprodução não
começa necessariamente imediatamente após a execução de video.play().
Além disso, desde o Chrome 50, uma chamada play() em um elemento <video> ou <audio>
retorna uma promessa, uma função que retorna um único resultado
de forma assíncrona. Se a reprodução for bem-sucedida, a promessa será cumprida e o
evento playing será acionado ao mesmo tempo. Se a reprodução falhar, a promessa será
rejeitada com uma mensagem de erro explicando a falha.
Veja o que está acontecendo:
video.play()começa a carregar o conteúdo do vídeo de forma assíncrona.video.pause()interrompe o carregamento do vídeo porque ele ainda não está pronto.video.play()rejeita de forma assíncrona.
Como não estamos processando a promessa de reprodução de vídeo no código, uma mensagem de erro aparece no Chrome DevTools.
Como corrigir o problema
Agora que entendemos a causa raiz, vamos ver o que podemos fazer para corrigir isso.
Primeiro, nunca presuma que um elemento de mídia (vídeo ou áudio) será reproduzido. Confira
a promessa retornada pela função play para saber se ela foi rejeitada. Vale
observar que a promessa não será cumprida até que a reprodução seja realmente
iniciada, o que significa que o código dentro do then() não será executado até que a mídia
esteja sendo reproduzida.
Exemplo: reprodução automática
<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>Exemplo: Abrir e pausar
<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>Isso é ótimo para este exemplo simples, mas e se você usar video.play() para
reproduzir um vídeo mais tarde?
Vou contar um segredo para você. Não é necessário usar video.play(). Você pode usar
video.load(), e aqui está como:
Exemplo: Buscar e reproduzir
<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>Suporte à promessa do Google Play
No momento da escrita, HTMLMediaElement.play() retorna uma promessa no
Chrome, Edge, Firefox, Opera e Safari.
Área perigosa
<source> em <video> faz com que a promessa play() nunca seja rejeitada
Para <video src="not-existing-video.mp4"\>, a promessa play() é rejeitada como
esperado, porque o vídeo não existe. Para <video><source
src="not-existing-video.mp4" type='video/mp4'></video>, a promessa play()
nunca é rejeitada. Isso só acontece se não houver fontes válidas.