Hai riscontrato questo errore multimediale imprevisto nella console JavaScript di Chrome DevTools?
o
Allora sei nel posto giusto. Non temere. Spiegherò la causa e come risolverlo.
Causa del problema
Di seguito è riportato il codice JavaScript che riproduce l'errore "Non rilevato (in promessa)" 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 per il seguente motivo: preload="none"
, la riproduzione del video non inizia necessariamente subito dopo l'esecuzione di video.play()
.
Inoltre, a partire da Chrome 50, una chiamata play()
su un elemento <video>
o <audio>
restituisce una funzione Promise, che restituisce un singolo risultato in modo asincrono. Se la riproduzione ha esito positivo, la Promise viene soddisfatta e contemporaneamente l'evento playing
viene attivato. Se la riproduzione non riesce, la funzionalità Promise viene rifiutata insieme a un messaggio di errore che spiega l'errore.
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 ad alta voce in modo asincrono.
Dal momento che non gestiamo la riproduzione video Promise nel nostro codice, in Chrome DevTools viene visualizzato un messaggio di errore.
Come risolvere il problema
Ora che abbiamo capito la causa principale, vediamo cosa possiamo fare per risolvere il problema.
Innanzitutto, non dare per scontato che venga riprodotto un elemento multimediale (video o audio). Osserva
la promessa restituita dalla funzione play
per vedere se è stata rifiutata. Tieni presente che il programma Promise non sarà valido finché la riproduzione non sarà effettivamente avviata, quindi il codice all'interno di then()
non verrà eseguito finché non è in corso la riproduzione dei contenuti multimediali.
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: Riproduci e metti 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>
È un'ottima cosa per questo semplice esempio, ma cosa succede se utilizzi video.play()
per
poter riprodurre un video in un secondo momento?
Ti dirò un segreto. Non devi necessariamente utilizzare video.play()
, puoi usare
video.load()
ed ecco come:
Esempio: Fetch & Play
<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>
Supporto Play promettente
Al momento della scrittura, HTMLMediaElement.play()
restituisce una promessa in
Chrome, Edge, Firefox, Opera e Safari.
Zona pericolosa
<source>
in <video>
fa una promessa di play()
che non rifiuta mai
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 ci sono origini valide.