解决新版本 Chrome 提示 DOMException: The play() request was interrupted

解决新版本 Chrome 提示

DOMException: The play() request was interrupted
大概在一些新版本的浏览器中,我们是用 audio 或者 video 进行媒体资源播放的时候,可能会在控制台看到这个输出:

Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). 

Or

Uncaught (in promise) DOMException: The play() request was interrupted by a new load request.  

如何触发?

<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
video.play(); // <-- This is asynchronous!
video.pause();
</script>

上面的代码会造成下面的异常错误:

Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). 

上面的 video 的 设置了 preload = ‘none’ ,视频并没有提前加载,因此在触发 video.play() 并不能立即播放。
从 Chrome 50 的版本后 触发 video.play 会返回一个 Promise 对象 ,如果播放成功,则 Promise 会触发,然后 playing 事件同时也会触发。如果播放失败,则会触发 Promise 的 reject,参数会带有错误的信息。
现在触发的顺序:

  • video.play() 异步的去加载 video 内容,
  • video.pause() 中断视频的加载,因为视频并没有就绪
  • video.play() 异步的 rejects
    因为我们并没有处理 video.play 的 Promise ,然后一个错误的信息会暴露出来。
    video.pause() 不光会打断一个视频的播放,而且会完全重置一个视频的播放的状态,包括 buffer 和 video.load这些

    修复

    <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(_ =>{
    // 这个时候可以安全的暂停
    video.pause();
    })
    .catch(error =>{

    });
    }
    </script>

如今现在 HTMLMediaElement.play() 支持返回 Promise 已经在 Chrome, Firefox, Opera, 以及 Safari Edge 实现了。