Fut*_*ure 5 javascript firefox google-chrome settimeout setinterval
当事件使用setTimeout / setInterval排队时,并且用户正在查看单独的选项卡时,Chrome和Firefox在执行事件之前强制执行至少1000ms的延迟。本文详细介绍了该行为。
前面已经在StackOverflow上对此进行了讨论,但是问题和答案仅适用于动画。显然,当用户重新进入选项卡时,动画只能被强制更新为最新状态。
但是该解决方案不适用于顺序音频。我有Web Audio API依次播放多个音频文件,并且setTimeout用于倒数播放下一个音频文件的时间。如果将选项卡放在后台,则每个模式之间的间隔会令人烦恼1秒钟,这是为高级音频设计的API中的一个极端缺陷。
您可以在各种HTML5音序器中看到这种行为,例如使用PatternSketch-只需输入模式,播放并转到另一个选项卡即可。
因此,我需要一种变通方法:一种在没有1000ms限制的情况下将事件排队的方法。有人知道吗?
我能想到的唯一解决方案是让window.postMessage每毫秒运行一次,并每次检查事件是否要执行。这绝对不利于性能。这是唯一的选择吗?
显然,没有为Web Audio API计划事件系统,因此这是毫无疑问的。
编辑:另一个答案是使用WebWorkers per /sf/answers/876580631/ - 这个答案有点具体,所以这里有一些更通用的内容:
间隔.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);
}
};
Run Code Online (Sandbox Code Playgroud)
和你的主程序:
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.
Run Code Online (Sandbox Code Playgroud)
完全丑陋,但你可以打开一个子弹出窗口。然而,这一切所做的只是将一些警告转移到子窗口,即如果子窗口最小化,则会出现 1000 毫秒问题,但如果它只是失去焦点,则不存在问题。话又说回来,如果它被关闭,那么它就会停止,但用户所要做的就是再次单击开始按钮。
所以,我想这并不能真正解决你的问题......但这是一个草稿:
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" />');
Run Code Online (Sandbox Code Playgroud)
我建议找出一种更好的方式来组织、写作等,但至少它应该为你指明正确的方向。它也应该可以在很多 diff 浏览器中工作(理论上,仅在 Chrome 中进行了测试)。剩下的事情就交给你了。
哦,不要忘记在父窗口掉落时自动关闭子窗口。
| 归档时间: |
|
| 查看次数: |
3669 次 |
| 最近记录: |