Apakah Anda baru saja menemukan error media yang tidak terduga ini di Konsol JavaScript Chrome DevTools?
atau
Anda berada di tempat yang tepat. Jangan khawatir. Kami akan menjelaskan penyebabnya dan cara memperbaikinya.
Penyebabnya
Berikut adalah beberapa kode JavaScript di bawah yang mereproduksi error "Uncaught (in promise)" yang Anda lihat:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
Kode di atas akan menghasilkan pesan error ini di Chrome DevTools:
_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
Karena video tidak dimuat karena preload="none"
, pemutaran video tidak
harus segera dimulai setelah video.play()
dieksekusi.
Selain itu, sejak Chrome 50, panggilan play()
pada elemen <video>
atau <audio>
menampilkan Promise, fungsi yang menampilkan satu hasil
secara asinkron. Jika pemutaran berhasil, Promise akan terpenuhi dan
peristiwa playing
diaktifkan secara bersamaan. Jika pemutaran gagal, Promise akan
ditolak beserta pesan error yang menjelaskan kegagalan tersebut.
Berikut ini yang terjadi:
video.play()
mulai memuat konten video secara asinkron.video.pause()
mengganggu pemuatan video karena belum siap.video.play()
menolak secara asinkron dengan keras.
Karena kita tidak menangani Promise pemutaran video dalam kode, pesan error akan muncul di Chrome DevTools.
Cara memperbaikinya
Setelah memahami akar masalahnya, mari kita lihat apa yang dapat kita lakukan untuk memperbaikinya.
Pertama, jangan pernah berasumsi bahwa elemen media (video atau audio) akan diputar. Lihat Promised yang ditampilkan oleh fungsi play
untuk melihat apakah promise ditolak. Perlu
diperhatikan bahwa Promise tidak akan terpenuhi hingga pemutaran benar-benar
dimulai, yang berarti kode di dalam then()
tidak akan dieksekusi hingga media
diputar.
Contoh: Autoplay
<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>
Contoh: Putar & Jeda
<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>
Hal ini bagus untuk contoh sederhana ini, tetapi bagaimana jika Anda menggunakan video.play()
agar
dapat memutar video nanti?
Saya akan memberi tahu rahasia. Anda tidak perlu menggunakan video.play()
, Anda dapat menggunakan
video.load()
dan berikut caranya:
Contoh: Ambil & Putar
<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>
Dukungan janji Play
Pada saat penulisan, HTMLMediaElement.play()
menampilkan promise di
Chrome, Edge, Firefox, Opera, dan Safari.
Zona bahaya
<source>
dalam <video>
membuat janji play()
tidak pernah ditolak
Untuk <video src="not-existing-video.mp4"\>
, promise play()
ditolak seperti
yang diharapkan karena video tidak ada. Untuk <video><source
src="not-existing-video.mp4" type='video/mp4'></video>
, promise play()
tidak pernah ditolak. Hal ini hanya terjadi jika tidak ada sumber yang valid.