你剛剛在 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 版起,在 <video>
或 <audio>
上呼叫 play()
元素會傳回 Promise,也就是傳回單一結果的函式
以非同步方式載入物件如果播放成功,代表 Promise 已執行完畢,
playing
事件會同時觸發。如果播放失敗, Promise 表示
並會顯示說明失敗的錯誤訊息
範例如下:
video.play()
會開始以非同步方式載入影片內容。video.pause()
在影片尚未就緒的情況下中斷載入。video.play()
會以非同步方式大聲拒絕。
由於我們未在程式碼中處理影片播放 Promise,因此系統會顯示錯誤訊息 顯示在 Chrome 開發人員工具中
修正方式
我們已瞭解根本原因,接著來看看該如何解決這個問題。
首先,請不用假設都會播放媒體元素 (影片或音訊)。查看
play
函式傳回的 Promise,確認是否遭到拒絕。是
值得注意的是,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。
危險區域
<video>
中的 <source>
讓 play()
承諾絕不會拒絕
針對 <video src="not-existing-video.mp4"\>
,play()
承諾拒絕為
確認影片不存在針對 <video><source
src="not-existing-video.mp4" type='video/mp4'></video>
,play()
承諾
一律不會拒絕只有在沒有有效的來源時才會發生這種情況。