HTML5 video.play 返回未决承诺

HTML5 video.play returning Pending promises

我正在尝试确定浏览器是否支持加载时自动播放。

我正在使用以下代码,它在 Android chrome 上运行良好,但对于桌面 Chrome none 中的 .catch 或 .然后被处决。承诺似乎只是 return 无限期的未决承诺。

这是一个实际的 Chrome 错误还是我不理解 Promise 在这里的工作原理?

const promise = document.createElement('video').play();

if (promise instanceof Promise) {
 promise.catch((error) => {
  // Check if it is the right error
  if (error.name === 'NotAllowedError') {
   autoPlayAllowed = false;
  } else {
   throw error;
  }
 }).then(() => {
  if (autoPlayAllowed) {
   // Autoplay is allowed - continue with initialization
   console.log('autoplay allowed')
  } else {
   // Autoplay is not allowed - wait for the user to trigger the play button manually
   console.log('autoplay NOT allowed')
  }
 });

} else {
 // Unknown if allowed
 console.log('autoplay unknown')
}

谢谢!

我不确定这是否是错误,但您需要先为您的视频设置 src,然后才能履行或拒绝播放承诺。

将其设置为空字符串 "" 将引发 "no supported source was found" 错误,但由于在您的原始代码中引发了无法识别的错误,因此 then 从未触发。 所以你可以依靠这个 "not found error" 来告诉自动播放有效,或者不要抛出错误去 then.

let autoPlayAllowed = true;
let v = document.createElement('video');
v.src = ""; // we need this

const promise = v.play();

if (promise instanceof Promise) {
  promise.catch(function(error) {
    console.log(error.message);
    // Check if it is the right error
    if (error.name === 'NotAllowedError') {
      autoPlayAllowed = false;
    } else {
      // Don't throw the error so that we get to the then
      // or throw it but set the autoPlayAllowed to true in here
    }
  }).then(function() {
    if (autoPlayAllowed) {
      // Autoplay is allowed - continue with initialization
      console.log('autoplay allowed')
    } else {
      // Autoplay is not allowed - wait for the user to trigger the play button manually
      console.log('autoplay NOT allowed')
    }
  });

} else {
  // Unknown if allowed
  // Note: you could fallback to simple event listeners in this case
  console.log('autoplay unknown')
}

请注意,只有 WHATWG 规范包含 MediaElement.play() 中的承诺,W3C 没有。因此,您可能希望回退到简单的事件侦听器,至少暂时如此。

哪些浏览器支持 Promisify MediaElement.play()

自 2016 年 2 月 pull request following on from an issue submitted on Jan 2016. It is connected to the recent decision to prevent MediaElements from autoplaying (except under special conditions, such as these, for iOS Safari 起,WHATWG 规范仅建议 MediaElement.play() 得到承诺。

W3C spec 仍然(截至 2017 年 11 月)似乎没有提到 MediaElement.play() 应该 return 一个承诺。

MediaElement.play() returnPromise 版本:

对于 Edge ,此更改的状态是 unknown(欢迎发表评论)

如何测试我的浏览器是否支持它?

Chrome团队发布了一个test page检查你自己的浏览器是否支持PromisifiedMediaElement.play()

如果支持,日志框会显示:

Attempting to play automatically...
The play() Promise fulfilled! Rock on!

否则,它只会打印这两行的第一行。

我应该如何普遍支持 MediaElement.play()

以下是 Jeff Posnick in a Google Developer blog post. Similar code is recommended in a WebKit blog post and by BitMovin, and they all derive from the original issue 归档推荐的最佳做法。

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.
  });
}

基本上:存储调用 MediaElement.play() 的结果,并且仅在结果未定义(例如 object 类型)时才将其作为 Promise 链进行操作。