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

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


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 intervalfunction 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 blockersdocument.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.