คุณเพิ่งพบข้อผิดพลาดเกี่ยวกับสื่อที่ไม่คาดคิดนี้ในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome คอนโซล JavaScript หรือไม่
หรือ
งั้นคุณก็มาถูกที่แล้ว อย่ากลัว ฉันจะอธิบายสาเหตุของปัญหานี้และวิธีแก้ไข
ปัญหานี้เกิดจากอะไร
นี่คือโค้ด JavaScript บางส่วนด้านล่างที่จำลองข้อผิดพลาด "ไม่ถูกตรวจจับ (ตามที่สัญญา)" ข้อผิดพลาดที่คุณเห็น:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
โค้ดด้านบนจะทำให้ข้อความแสดงข้อผิดพลาดนี้ในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
_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()
ปฏิเสธไม่พร้อมกันเสียงดัง
เนื่องจากเราไม่ได้จัดการการเล่นวิดีโอ Promise ในโค้ดของเรา ข้อความแสดงข้อผิดพลาด จะปรากฏในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
วิธีแก้ไข
เมื่อทราบสาเหตุของปัญหาแล้ว มาดูกันว่าจะแก้ปัญหานี้ได้อย่างไรบ้าง
อย่างแรก อย่าคิดว่าจะมีการเล่นองค์ประกอบสื่อ (วิดีโอหรือเสียง) ดูที่
Promise แสดงผลโดยฟังก์ชัน play
เพื่อดูว่าถูกปฏิเสธหรือไม่ ใช่เลย
โปรดทราบว่า Promise จะไม่
บรรลุผลจนกว่าการเล่นจะจบลง
เริ่มทำงาน ซึ่งหมายความว่าโค้ดภายใน 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>
การสนับสนุนจาก Play
ในขณะที่เขียน 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()
ไม่เคยปฏิเสธ ซึ่งจะเกิดขึ้นเฉพาะในกรณีที่ไม่มีแหล่งที่มาที่ถูกต้องเท่านั้น