我正在做一个沉重的“科学”(即不显示数据)webgl计算。 Webgl不能放在一个worker中,并且做了很多webgl会阻塞整个浏览器,所以我把计算切成块,然后我在setTimeout()函数中计算每个块(在调用getError()之后刷新opengl队列)。我在块之间留下了一些时间,以便浏览器有时间从主UI队列中清除一些UI事件,这使整个事情感觉有点迟钝。
我的问题是,当隐藏选项卡时,setTimeout被限制为一秒钟,这对我来说太慢了。
有没有比我做的更好的解决方案?显然requestAnimationFrame()不起作用,因为它永远不会在隐藏的选项卡中回调(并且它在可见的时候太慢了)。
隐藏状态下是否存在非限制时间事件?我尝试使用window.postMessage(),但它仍然太快,整个浏览器感觉很慢。
这是我研究的现状:
function drawTile(sequenceIndex) {
if (sequenceIndex < sequence.length) {
var x = sequence[sequenceIndex][0];
var y = sequence[sequenceIndex][1];
setTilePos(x, y);
modelStage.render(renderer, modelBuffer);
minkowskiPass.render(renderer, minkowskiBuffer, modelBuffer);
copyPass.quad.position.x = x;
copyPass.quad.position.y = y;
copyPass.render(renderer, null, minkowskiBuffer);
var gl = renderer.getContext();
gl.getError();
sequenceIndex++;
if (document.visibilityState != "hidden") {
setTimeout(function () {
drawTile(sequenceIndex);
}, 10);
} else {
//window.postMessage is not rate limited then the tab is hidden
// we need to slow the computation by an event, otherwise the whole browser is unresponsive.
$(window).one('message', function () {
drawTile(sequenceIndex);
});
window.postMessage('lol', '*');
}
} else
console.timeEnd('computation');
}
console.time('computation');
drawTile(0);
答案 0 :(得分:1)
对于任何需要它的人来说,这是另一个错综复杂的解决方法;您可以使用Web Audio API生成函数调用:
var setTimeout2 = (function () {
var samples = 2048;
var fns = [];
var context = new AudioContext();
var source = context.createBufferSource();
var node = context.createScriptProcessor(samples, 1, 1);
// This gets fired every ~46 milliseconds. You can change
// `samples` to another valid value (256, 512, 1024, 2048,
// 4096, 8192, or 16384); then it'll get called every
// `samples / context.sampleRate` seconds (~46 ms for
// `samples == 2048` and `context.sampleRate == 44100`).
node.onaudioprocess = function (e) {
fns = fns.filter(function (fn) {
return !fn(Date.now() - fn.t);
});
};
source.connect(node);
node.connect(context.destination);
window.do_not_garbage_collect = [context, source, node];
return function (fn) {
fn.t = Date.now();
fns.push(fn);
};
}());
// Use like this:
setTimeout2(function (t) {
console.log(t);
// End after 1 second.
if (t > 1000)
return true;
})
答案 1 :(得分:-1)
也许有一个工作线程也运行一个 postMessage循环和一小部分时间(每n次迭代),暂停还是恢复主线程?