Hai appena riscontrato questo errore multimediale imprevisto nella console JavaScript di Chrome DevTools?
o
Allora sei nel posto giusto. Non preoccuparti. Ti spiegherò cosa causa il problema e come risolverlo.
Qual è la causa
Di seguito è riportato un codice JavaScript che riproduce l'errore "Uncaught (in promise)" visualizzato:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
Il codice riportato sopra genera questo messaggio di errore in Chrome DevTools:
_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
Poiché il video non viene caricato a causa di preload="none"
, la riproduzione non necessariamente inizia subito dopo l'esecuzione di preload="none"
.video.play()
Inoltre, a partire da Chrome 50, una chiamata play()
a un elemento <video>
o <audio>
restituisce una promessa, una funzione che restituisce un singolo risultato
in modo asincrono. Se la riproduzione va a buon fine, la promessa viene soddisfatta e contemporaneamente viene attivato l'evento playing
. Se la riproduzione non va a buon fine, la promessa viene rifiutata insieme a un messaggio di errore che spiega il problema.
Ecco cosa succede:
video.play()
inizia a caricare i contenuti video in modo asincrono.video.pause()
interrompe il caricamento del video perché non è ancora pronto.video.play()
rifiuta in modo asincrono ad alto volume.
Poiché non gestiamo la promessa di riproduzione del video nel nostro codice, viene visualizzato un messaggio di errore in Chrome DevTools.
Come risolvere il problema
Ora che conosciamo la causa principale, vediamo cosa possiamo fare per risolvere il problema.
Innanzitutto, non dare mai per scontato che un elemento multimediale (video o audio) venga riprodotto. Controlla la promessa restituita dalla funzione play
per vedere se è stata rifiutata. È importante notare che la promessa non verrà soddisfatta finché la riproduzione non sarà effettivamente iniziata, il che significa che il codice all'interno di then()
non verrà eseguito finché i contenuti multimediali non saranno in riproduzione.
Esempio: Riproduzione automatica
<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>
Esempio: Riproduzione e messa in pausa
<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>
Perfetto per questo semplice esempio, ma cosa succede se utilizzi video.play()
per poter riprodurre un video in un secondo momento?
Ti svelerò un segreto. Non devi utilizzare video.play()
, puoi utilizzare
video.load()
ed ecco come:
Esempio: Gioca e recupera
<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>
Assistenza per la promessa di Google Play
Al momento della stesura di questo articolo, HTMLMediaElement.play()
restituisce una promessa in Chrome, Edge, Firefox, Opera e Safari.
Zona pericolosa
<source>
in <video>
fa sì che la promessa play()
non venga mai rifiutata
Per <video src="not-existing-video.mp4"\>
, la promessa play()
viene rifiutata come previsto perché il video non esiste. Per <video><source
src="not-existing-video.mp4" type='video/mp4'></video>
, la promessa play()
non viene mai rifiutata. Ciò si verifica solo se non sono presenti origini valide.