HTMLMediaElement.play() 会返回 promise

在网络上自动播放音频和视频是一项强大的功能,但在不同平台上受到不同的限制。目前,大多数桌面浏览器始终允许网页通过 JavaScript 开始播放 <video><audio>,而无需用户互动。不过,大多数移动浏览器都要求用户明确执行手势,JavaScript 才能发起播放。这有助于确保移动用户(其中许多用户需要付费使用带宽或可能身处公共环境)不会在未明确与网页互动的情况下意外开始下载和播放媒体。

过去,很难确定是否需要用户互动才能开始播放,以及检测尝试(自动)播放失败时发生的失败情况。虽然有各种权宜解决方法,但效果并不理想。我们早就应该对底层 play() 方法进行改进来解决此不确定性问题,现在,我们已将此改进引入到网络平台,并在 Chrome 50 中进行了初始实现。

<video><audio> 元素的 play() 调用现在会返回 Promise。如果播放成功,则 promise 会执行,如果播放失败,则 promise 会被拒绝,并会显示说明失败原因的错误消息。这样一来,您就可以编写直观的代码,如下所示:

var playPromise = document.querySelector('video').play();

// In browsers that don’t yet support this functionality,
// playPromise won’t be defined.
if (playPromise !== undefined) {
    playPromise.then(function() {
    // Automatic playback started!
    }).catch(function(error) {
    // Automatic playback failed.
    // Show a UI element to let the user manually start playback.
    });
}

除了检测 play() 方法是否成功之外,基于 Promise 的新接口还可让您确定 play() 方法何时成功。在某些上下文中,网络浏览器可能会决定延迟开始播放,例如,桌面版 Chrome 在标签页可见之前不会开始播放 <video>。只有在实际开始播放后,Promise 才会执行,这意味着,只有在媒体播放时,then() 中的代码才会执行。以前用于确定 play() 是否成功的方法(例如,等待一段时间来等待 playing 事件,如果未触发该事件,则假定失败)在延迟播放场景中容易出现假负例。

我们发布了此新功能的实例。在支持这种基于 Promise 的接口的浏览器(例如 Chrome 50)中查看该文档。请注意:当您访问该页面时,系统会自动播放音乐。(当然,除非它不存在!)

危险区域

<video> 中的 <source> 会使 play() 承诺永不拒绝

对于 <video src="not-existing-video.mp4"\>,由于视频不存在,play() 承诺会按预期遭拒。对于 <video><source src="not-existing-video.mp4" type='video/mp4'></video>play() promise 永远不会拒绝。只有在没有有效来源时,才会出现这种情况。

Chromium bug