当事件使用setTimeout/setInterval排队时,并且用户正在查看单独的选项卡时,Chrome和Firefox在执行事件之前强制执行至少1000ms的延迟。 This article详细说明了行为。
前面已经在StackOverflow上对此进行了讨论,但是问题和答案仅适用于动画。显然,当用户重新进入选项卡时,动画只能被强制更新为最新状态。
但是该解决方案不适用于定序音频。我有Web Audio API依次播放多个音频文件,并且setTimeout用于倒数播放下一个音频文件的时间。如果将选项卡放在背景中,则每个模式之间会出现1秒钟的烦人间隙-这是专为高级音频设计的API中的一个极端缺陷。
您可以在各种HTML5定序器中看到这种行为,例如使用PatternSketch-只需输入一个模式,播放,然后转到另一个选项卡即可。
因此,我需要一种变通方法:一种在没有1000ms钳位的情况下将事件排队的方法。有人知道吗?
最佳答案
编辑:另一个答案是每个https://stackoverflow.com/a/12522580/1481489使用WebWorker
-这个答案有点具体,所以这里有一些更通用的东西:
interval.js
var intervalId = null;
onmessage = function(event) {
if ( event.data.start ) {
intervalId = setInterval(function(){
postMessage('interval.start');
},event.data.ms||0);
}
if ( event.data.stop && intervalId !== null ) {
clearInterval(intervalId);
}
};
和你的主程序:
var stuff = { // your custom class or object or whatever...
first: Date.now(),
last: Date.now(),
callback: function callback() {
var cur = Date.now();
document.title = ((cur-this.last)/1000).toString()+' | '+((cur-this.first)/1000).toString();
this.last = cur;
}
};
var doWork = new Worker('interval.js');
doWork.onmessage = function(event) {
if ( event.data === 'interval.start' ) {
stuff.callback(); // queue your custom methods in here or whatever
}
};
doWork.postMessage({start:true,ms:250}); // tell the worker to start up with 250ms intervals
// doWork.postMessage({stop:true}); // or tell it just to stop.
丑陋的,但是您可以打开一个子弹出窗口。但是,所有这些操作只是将一些警告转移到了子窗口上,即如果最小化了子窗口,则会出现1000ms的问题,但是如果它根本不在焦点上,就没有问题了。然后,如果它关闭了,它就会停止,但是用户要做的就是再次单击“开始”按钮。
因此,我想这并不能真正解决您的问题...但这是一个草稿:
var mainIntervalMs = 250;
var stuff = { // your custom class or object or whatever...
first: Date.now(),
last: Date.now(),
callback: function callback(){
var cur = Date.now();
document.title = ((cur-this.last)/1000).toString()+' | '+((cur-this.first)/1000).toString();
this.last = cur;
}
};
function openerCallbackHandler() {
stuff.callback(); // queue your custom methods in here or whatever
}
function openerTick(childIntervalMs) { // this isn't actually used in this window, but makes it easier to embed the code in the child window
setInterval(function() {
window.opener.openerCallbackHandler();
},childIntervalMs);
}
// build the popup that will handle the interval
function buildIntervalWindow() {
var controlWindow = window.open('about:blank','controlWindow','width=10,height=10');
var script = controlWindow.document.createElement('script');
script.type = 'text/javascript';
script.textContent = '('+openerTick+')('+mainIntervalMs+');';
controlWindow.document.body.appendChild(script);
}
// write the start button to circumvent popup blockers
document.write('<input type="button" onclick="buildIntervalWindow();return false;" value="Start" />');
我建议您找到一种更好的组织,编写等方式,但是至少它应该为您指明正确的方向。它也应该可以在许多差异浏览器中使用(理论上,仅在chrome中测试)。我让你休息。
哦,如果父窗口掉落,别忘了建立子窗口的自动关闭功能。
关于javascript - setTimeout/setInterval在后台标签(Chrome和Firefox)中滞后1000ms,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19475894/