setTimeout/setInterval 1000ms lag in background tabs (Chrome and Firefox)

扶醉桌前 提交于 2019-11-28 11:30:16
zamnuts

EDIT: Another answer is to use WebWorkers per https://stackoverflow.com/a/12522580/1481489 - this answer is a little specific, so here's something more generic:

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

and your main program:

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.

Totally ugly, but you could open up a child popup window. However, all this does is transfer some of the caveats to the child window, i.e. if child window is minimized the 1000ms problem appears, but if it is simply out of focus, there isn't an issue. Then again, if it is closed, then it stops, but all the user has to do is click the start button again.

So, I suppose this doesn't really solve your problem... but here's a rough draft:

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" />');

I'd recommend working out a better way to organize, write, etc. but at the least it should point you in the right direction. It should also work in a lot of diff browsers (in theory, only tested in chrome). I'll leave you to the rest.

Oh, and don't forget to build in auto-closing of the child window if the parent drops.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!