Javascript 如何防止“播放()请求被暂停()调用中断”错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36803176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent "The play() request was interrupted by a call to pause()" error?
提问by Owen M
I made a website where if the user clicks, it plays a sound. To prevent the sound from overlapping, I had to add the code:
我做了一个网站,如果用户点击,它会播放声音。为了防止声音重叠,我不得不添加代码:
n.pause();
n.currentTime = 0;
n.play();
But that causes the error:
The play() request was interrupted by a call to pause()
To come up each time the sound event is triggered right after another trigger. The sounds still plays fine, but I want to prevent this error message constantly popping up. Any ideas?
但这会导致错误:
The play() request was interrupted by a call to pause()
每次在另一个触发之后触发声音事件时都会出现。声音仍然可以正常播放,但我想防止此错误消息不断弹出。有任何想法吗?
采纳答案by JohnnyCoder
I have encountered this issue recently as well - this could be a race condition between play()
and pause()
. It looks like there is a reference to this issue, or something related here.
我最近也遇到了这个问题 - 这可能是play()
和之间的竞争条件pause()
。看起来有一个关于这个问题的参考,或者这里有一些相关的东西。
As @Patrickpoints out, pause
does not return a promise (or anything), so the above solution won't work. While MDN does not have docs on pause()
, in the WC3 draft for Media Elements, it says:
正如@Patrick指出的那样,pause
不返回承诺(或任何东西),因此上述解决方案不起作用。虽然 MDN 没有关于 的文档pause()
,但在Media Elements的WC3 草案中,它说:
media.pause()
Sets the paused attribute to true, loading the media resource if necessary.
媒体暂停()
将 paused 属性设置为 true,必要时加载媒体资源。
So one might also check the paused
attribute in their timeout callback.
因此,您还可以检查paused
其超时回调中的属性。
Based on this great SO answer, here's a way you can check if the video is (or isn't) truly playing, so you can safely trigger a play() without the error.
基于这个很好的 SO answer,这里有一种方法可以检查视频是否正在(或不是)真正播放,因此您可以安全地触发 play() 而不会出现错误。
var isPlaying = video.currentTime > 0 && !video.paused && !video.ended
&& video.readyState > 2;
if (!isPlaying) {
video.play();
}
回答by Nebojsa Sapic
After hours of seaching and working, i found perfect solution.
经过数小时的搜索和工作,我找到了完美的解决方案。
// Initializing values
var isPlaying = true;
// On video playing toggle values
video.onplaying = function() {
isPlaying = true;
};
// On video pause toggle values
video.onpause = function() {
isPlaying = false;
};
// Play video function
function playVid() {
if (video.paused && !isPlaying) {
video.play();
}
}
// Pause video function
function pauseVid() {
if (!video.paused && isPlaying) {
video.pause();
}
}
After that, you can toggle play/pauseas fast as you can, it will work properly.
之后,您可以尽快切换播放/暂停,它会正常工作。
回答by Patrick
I have hit this issue, and have a case where I needed to hit pause() then play() but when using pause().then() I get undefined.
我遇到了这个问题,并且有一个案例,我需要点击 pause() 然后 play() 但是当使用 pause().then() 时,我得到了未定义。
I found that if I started play 150ms after pause it resolved the issue. (Hopefully Google fixes soon)
我发现如果我在暂停后 150 毫秒开始播放它解决了这个问题。(希望谷歌尽快修复)
playerMP3.volume = 0;
playerMP3.pause();
//Avoid the Promise Error
setTimeout(function () {
playerMP3.play();
}, 150);
回答by Fran?ois Beaufort
I've just published an article about this exact issue at https://developers.google.com/web/updates/2017/06/play-request-was-interruptedthat tells you exactly what is happening and how to fix it.
我刚刚在https://developers.google.com/web/updates/2017/06/play-request-was-interrupted上发表了一篇关于这个确切问题的文章,它告诉你到底发生了什么以及如何解决它。
回答by gest
try it
尝试一下
n.pause();
n.currentTime = 0;
var nopromise = {
catch : new Function()
};
(n.play() || nopromise).catch(function(){}); ;
回答by Dmitry Kovganov
This solution helped me:
这个解决方案帮助了我:
n.cloneNode(true).play();
回答by Sharpey
Solutions proposed here either didn't work for me or where to large, so I was looking for something else and found the solution proposed by @dighan on bountysource.com/issues/
此处提出的解决方案要么对我不起作用,要么对我不起作用,所以我正在寻找其他解决方案,并在bountysource.com/issues/上找到了 @dighan 提出的解决方案
So here is the code that solved my problem:
所以这是解决我的问题的代码:
var media = document.getElementById("YourVideo");
const playPromise = media.play();
if (playPromise !== null){
playPromise.catch(() => { media.play(); })
}
It still throws an error into console, but at least the video is playing :)
它仍然会向控制台抛出错误,但至少视频正在播放:)
回答by The Blue Crayon
Depending on how complex you want your solution, this may be useful:
根据您想要解决方案的复杂程度,这可能很有用:
var currentPromise=false; //Keeps track of active Promise
function playAudio(n){
if(!currentPromise){ //normal behavior
n.pause();
n.currentTime = 0;
currentPromise = n.play(); //Calls play. Will store a Promise object in newer versions of chrome;
//stores undefined in other browsers
if(currentPromise){ //Promise exists
currentPromise.then(function(){ //handle Promise completion
promiseComplete(n);
});
}
}else{ //Wait for promise to complete
//Store additional information to be called
currentPromise.calledAgain = true;
}
}
function promiseComplete(n){
var callAgain = currentPromise.calledAgain; //get stored information
currentPromise = false; //reset currentPromise variable
if(callAgain){
playAudio(n);
}
}
This is a bit overkill, but helps when handling a Promise in unique scenarios.
这有点矫枉过正,但在特殊情况下处理 Promise 时会有所帮助。
回答by Christoph Eberl
Maybe a better solution for this as I figured out. Spec says as cited from @JohnnyCoder :
正如我发现的那样,也许这是一个更好的解决方案。Spec 引用自 @JohnnyCoder :
media.pause()
Sets the paused attribute to true, loading the media resource if necessary.
媒体暂停()
将 paused 属性设置为 true,必要时加载媒体资源。
--> loading it
--> 加载
if (videoEl.readyState !== 4) {
videoEl.load();
}
videoEl.play();
indicates the readiness state of the media HAVE_ENOUGH_DATA = 4
表示媒体的就绪状态 HAVE_ENOUGH_DATA = 4
Basically only load the video if it is not already loaded. Mentioned error occurred for me, because video was not loaded. Maybe better than using a timeout.
基本上只加载尚未加载的视频。提到的错误发生在我身上,因为视频没有加载。也许比使用超时更好。
回答by ryanrain
removed all errors: (typescript)
删除了所有错误:(打字稿)
audio.addEventListener('canplay', () => {
audio.play();
audio.pause();
audio.removeEventListener('canplay');
});