Can setInterval result in other scripts in the page blocking?
I’m working on a project to convert a Gmail related bookmarklet into a Google Chrome extension. The bookmarklet uses the gmail greasemonkey API to interact with the gmail page. The JavaScript object for the API is one of the last parts of the Gmail page to load and is loaded into the page via XMLHttpRequest. Since I need access to this object, and global JavaScript variables are hidden from extension content scripts, I inject a script into the gmail page that polls for the variable’s definition and then accesses it. I’m doing the polling using the setInterval function. This works about 80% of the time. The rest of the time the polling function keeps polling until reaching a limit I set and the greasemonkey API object is never defined in the page.
Injected script sample:
var attemptCount = 0;
var attemptLoad = function(callback) {
if (typeof(gmonkey) != "undefined"){
clearInterval(intervalId); // unregister this function for interval execution.
gmonkey.load('1.0', function (gmail) {
self.gmail = gmail;
if (callback) { callback(); }
});
}
else {
attemptCount ++;
console.log("Gmonkey not yet loaded: " + attemptCount );
if (attemptCount > 30) {
console.log("Could not fing Gmonkey in the gmail page after thirty seconds. Aborting");
clearInterval(intervalId); // unregister this function for interval execution.
};
}
};
var intervalId = setInterval(function(){attemptLoad(callback);}, 1000);
Javascript is single threaded (except for web workers which we aren’t talking about here). That means that as long as the regular javascript thread of execution is running, your
setInterval()timer will not run until the regular javascript thread of execution is done.Likewise, if your
setInterval()handler is executing, no other javascript event handlers will fire until yoursetInterval()handler finishes executing it’s current invocation.So, as long as your
setInterval()handler doesn’t get stuck and run forever, it won’t block other things from eventually running. It might delay them slightly, but they will still run as soon as the currentsetInterval()thread finishes.Internally, the javascript engine uses a queue. When something wants to run (like an event handler or a
setInterval()callback) and something is already running, it inserts an event into the queue. When the current javascript thread finishes execution, the JS engine checks the event queue and if there’s something there, it picks the oldest event there and calls its event handler.Here are a few other references on how the Javascript event system works:
How does JavaScript handle AJAX responses in the background?
Are calls to Javascript methods thread-safe or synchronized?
Do I need to be concerned with race conditions with asynchronous Javascript?