setTimeOut() and setInterval() in Node [duplicate] - javascript

This question already has answers here:
How does setTimeout work in Node.JS?
(5 answers)
Closed 6 years ago.
If I call setTimeOut() for say, 10 seconds from now, then execute a set of long running commands, does Node.js/JavaScript wait until those commands finish executing the function set up in setTimeOut? Is the same true with setInterval()?
Are there any things to watch out for if I'm suing both setTimeOut() and setInterval() in the code where tasks may end up being executed around the same time?
I'm using the node-cron (https://github.com/kelektiv/node-cron/blob/master/lib/cron.js) library and I see that it uses setTimeOut. I'm trying to add some tasks using setInterval().

Timer events in node.js are not guaranteed to be called at an accurate time.
If I call setTimeOut() for say, 10 seconds from now, then execute a
set of long running commands, does Node.js/JavaScript wait until those
commands finish executing the function set up in setTimeOut?
Yes, it waits until the current code executing in node.js is done before it can serve the next timer event.
Is the same true with setInterval()?
Yes, same mechanism for setInterval().
Here's some explanation of how the node.js system works.
node.js is a single threaded event-driven system (technically threads are used inside of node.js, but it only runs one single thread of your JS code).
When you use setTimeout() or setInterval() some internal mechanism inside of node.js uses system timers to know when the next timer should fire. At that moment, an event is inserted into the node.js event queue. If node.js is doing nothing at that moment, then the event is triggered immediately and the appropriate callback function is called immediately.
But, if node.js is busy running code and if other events are in front of the timer event in the event queue, then the timer event will not be triggered immediately.
Instead, node.js will wait until the current thread of execution in node.js is done and then, and only then, the next event in the event queue will be pulled out and the appropriate callback for that event will get called.
So, if you have some piece of long running node.js code, it will block all other events (including timer events) until it is done and node.js can get back to pulling the next event out of the event queue.

The answer is: maybe but probably not.
When things are async, there isn't necessarily any guarantee what's going to get called when. When async things are called, it'll get added to an internal queue and it'll process the queue. Odds are, they will finish, but it is not something you should rely on.
Instead, what you should do is trigger something to explicitly indicate that it finished. There are lots of ways to go about it, such as callbacks and Promises. You could even set a boolean that indicates the state and check it before the dependent step.
let aDone = false;
setTimeout(() => { aDone = true; }, 1000);
const startInterval = () => {
if (!aDone) {
setTimeout(startInterval, 200); // try again in 200ms
}
setInterval(() => { /* do something */ }, 1000);
};
startInterval(); // kick off the interval check

Related

Node JS SetTimeOut call back

I have been going throug node JS training on newboston channel (link https://www.youtube.com/watch?v=KsjrN-T3ZCs). and Example was given on how Node provides better performance is shown below
function placeAnOrder(orderNumber) {
console.log("Order placed", orderNumber);
cookAndDeliver(function () {
console.log("Delivered order", orderNumber);
});
};
function cookAndDeliver(callback){
setTimeout(callback, 5000);
};
placeAnOrder(1);
placeAnOrder(11);
placeAnOrder(111);
placeAnOrder(1111);
placeAnOrder(11111);
Should you run the sample, you will notice that first all order placed at once, which is normal, and then all of the orders are also delivered once, which is not normal since there is already a timeout constraint of 5 seconds applied per call.
The explanation given by the video was that the call back is none-obstructive and the code will execute unintrrupted, which I concur with, what I don't get is why the node did not honor the timeout value?
My guess is that since it operates in an asynchronous mode then it means that a separate thread is going to handle each call, is my assumption correct?
Here's the sequence of events:
Call first placeAnOrder()
It calls cookAndDeliver()
It calls setTimeout()
The setTimeout() schedules a timer event for 5 seconds from now and returns immediately.
Call second placeAnOrder()
It calls cookAndDeliver()
It calls setTimeout()
The setTimeout() schedules a timer event for 5 seconds from now and returns immediately.
Call second placeAnOrder()
It calls cookAndDeliver()
It calls setTimeout()
The setTimeout() schedules a timer event for 5 seconds from now and returns immediately.
Repeat this two more times for a total of 5 timers scheduled to go about 5 seconds from now
The Javascript interpreter returns control back to the event loop as it has nothing further to do for awhile
Then about 5 seconds from now, an internal part of Javascript places the first timer event into the event queue
If the Javascript interpreter is not doing anything at that moment, then it fires that event and calls the callback associated with that timer event.
That callback executes.
When that callback executes, there's another timer event in the event queue and the JS interpreter calls its callback to process it.
After that callback is done, the next 3 timer events are pulled, one at a time, from the event queue and their callbacks are executed.
There are no Javascript threads here. Javascript in node.js is single threaded. Everything runs through a central event queue. There may be internals to Javascript that use threads in order to carry out asynchronous operations (for example, async file I/O does use threads internal to its implementation, but not for running the Javascript). When those threads are done, they place an event into the event queue and when the single node.js Javascript thread is done executing what it was doing, it then grabs the next event from the event queue and executes the callback associated with it.
My guess is that since it operates in an asynchronous mode then it means that a separate thread is going to handle each call, is my assumption correct?
No, that is not correct. setTimeout() schedules a timer event for some future time. There is no Javascript thread associated with a timer event. There may or may not be a single system thread that manages all timer events (that is implementation specific and doesn't really matter - It could also be that whenever Javascript gets back to the event loop, it just checks to see if its time to fire the next timer event). When the time arrives for the timer to fire, an event is inserted into the Javascript event queue. The JS interpreter then picks up that event from the event loop, the next time it's done processing and is looking for the next event to process.
An example was given on how Node provides better performance is shown below
I think what they were trying to show is that because of the node.js asynchronous event-driven design, there are NOT multiple threads for asynchronous events like timers. That allows it to scale better when there are lots of asynchronous operations in flight at the same time because its model is more efficient than a model where there is a system thread for every timer.
Should you run the sample, you will notice that first all order placed at once, which is normal, and then all of the orders are also delivered once, which is not normal since there is already a timeout constraint of 5 seconds applied per call.
The code essentially runs 5 setTimeout() calls in a row that all set a timer to fire 5 seconds from now. setTimeout() is non-blocking. That means it schedules the timer for 5 seconds from now and then IMMEDIATELY goes on to the next line of code which also schedules a timer for 5 seconds from now. So you end up with 5 timers all scheduled for about 5 seconds from now (perhaps varying only be a few ms of execution time from one setTimeout() call to the next. The end result is that all 5 timers will fire in about 5 seconds and they will fire in the order they were scheduled.
The explanation given by the video was that the call back is none-obstructive and the code will execute unintrrupted, which I concur with, what I don't get is why the node did not honor the timeout value?
Because setTimeout() is non-blocking (as are all asynchronous operations in node.js). It schedules the timer for some future time and then immediately returns (that's the non-blocking part). It does not wait 5 seconds to return. It returns immediately and executes whatever code comes next. Then 5 seconds from now (when the JS interpreter has nothing else to do), the timer callback will get called.
It does honor the timeout. The timeout is for the callback, and not the execution of the function. So what happened is that all of your function calls executed asynchronously, and they all waited five seconds, and they all returned. So they all took five seconds between starting and finishing. Node doesn't have to wait for the first function to complete before the second one to complete.
Basically for a non-trivial example i.e. waiting on a db call. you don't have to wait for one db call to finish before sending a second db call. And if the db is threaded, you can get the results pretty much at the same time.

How can a script and setTimeout/setInterval work together in NodeJS?

Reading through the NodeJS Event Loop description I wonder how setTimeout and setInterval can actually work.
The page says NodeJS first runs the given script (let REPL alone for now) and then enters the event loop. But what if I call setTimeout in that script and expect it to trigger while the script is still running? Isn't that the normal case actually? According to the description the timer callback will not be triggered before the main script ends, which sounds really weird to me.
For those interested, here's the NodeJS outer even loop (there are actually 2 nested loops): https://github.com/nodejs/node/blob/master/src/node.cc#L4526
let's do this by example
setTimeout(function(){
print('there');
});
print('hi');
this will print hi then there
here's what happen
the script will be proccessed until last line and when ever it finds a timer function
it will add it to a queue which will be handled later at the end of the execution by the queue scheduler
loop queue => [ setTimeout ]
before exit there should be a scheduler, some kind of a loop to check if we
have something in the queue and handle them, then once queue is out of all timers the loop
will exit.
let's suppose we call setTimeout inside setInterval
setInterval(function(){
setTimeout(function(){
print('hi')
}, 500);
}, 1000);
loop queue => [ setInterval ]
after 1000 ms
setInterval will be fired and the inner setTimeout will be added to the queue
loop queue => [ setTimeout, setInterval ]
now we get back to the main loop which will wait for another 500 ms
an fire the inner setTimeout function, then remove it from the queue
because setTimeout should be run once.
loop queue => [ setInterval ]
back to the main loop, we still have items in the queue, so it will wait
another 500 ms and fire again ( 500 + 500 = 1000 ms)
the inner setTimeout function will be added to the queue again
loop queue => [ setTimeout, setInterval ]
back to the main queue agin and again ...
Now this is simply how timers work, they are not meant to handle blocking code, it's
a way to run code at some intervals
setInterval(function(){
// do something long running here
while (1) {}
setTimeout(function(){
print('hi')
}, 500);
}, 1000);
main loop will block here and the inner timeout will not be added to the queue, so this
is a bad idea
nodejs and event loop in general are good with network operations because they don't block when
used with select for example.
setInterval(function(){
// check if socket has something
if (socketHasData( socket )){
processSocketData( socket );
}
// do something else that does not block
// maybe schedule another timer here
print('hello');
}, 1000);
libuv which is the event loop used in nodejs, uses threads to handle some
blocking operations like IO operations, open/read/write files
[EDIT] humm re-reading your initial post, I think I know what bugs you. You mentioned nodejs in your post, implying you might be coding a server.
If you are not really familiar with server side JavaScript and more used to php server for example it might be very confusing indeed.
With a php server, a request creates a new thread that will handle it and when the main script (as you call it) ends, then the thread is killed and nothing else runs on the server (except for the webserver that listens to request, like nginx or apache).
With nodejs, it's different. The main thread is alone and always running. So when a request arrives, callbacks are fired but they are still in that single thread. Said otherwise: the main script never ends (except when you kill it or that your server crashes :) )
Well, that is accurate. Because of the single-threaded nature of JavaScript, if a timer ends while the main thread is busy, the timer's callback will wait.
When you do
setTimeout(callback, 1000)
You are not saying "I want this callback to be called in exactly 1s" but actually "I want this callback to be called in, at least, 1s"
This article by John Resig is an excellent read and goes through the details of the JavaScript's timers https://johnresig.com/blog/how-javascript-timers-work/
But what if I call setTimeout in that script and expect it to trigger while the script is still running?
You don't expect that. You expect your synchronous code run to completion way before the timeout occurs.
If the script is still running, because it's doing something blocking - it hangs - then the timeout callback doesn't get a chance to execute, it will wait. That's exactly why we need to write non-blocking code.
Isn't that the normal case actually?
No. Most of the time no JS is executing, the event loop is idling (while there might be background tasks doing the heavy lifting).
Given that Node is single threaded, it (v8 engine) always executes the current script before moving on to the next one. So when we start a node server with a main script, it loads, parses, compiles and executes that script first, before it runs anything else. Only if the current running script hits an I/O call it gets bumped out to the back of the event loop, giving other scripts or setTimeout callbacks a chance to execute. This is the very nature of JavaScript engine and the reason Node is not considered good for long running, in-memory CPU intensive tasks.
As #atomrc said in his answer, setTimeout and setInterval are just a hint to node to run the callbacks after the timeout period, there are no guarantees.

Javascript internals - clearTimeout just before it fires

Let's say I do this:
var timer = setTimeout(function() {
console.log("will this happen?");
}, 5000);
And then after just less than 5 seconds, another callback (from a network event in NodeJS for example) fires and clears it:
clearTimeout(timer);
Is there any possibility that the callback from the setTimeout call is already in the queue to be executed at this point, and if so will the clearTimeout be in time to stop it?
To clarify, I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it, but the other callback is currently running so the message is added to the queue. It seems like one of those race condition type things that would be easy to not account for.
Even though Node is single thread, the race condition the question describes is possible.
It can happen because timers are triggered by native code (in lib_uv).
On top of that, Node groups timers with the same timeout value. As a result, if you schedule two timers with the same timeout within the same ms, they will be added to the event queue at once.
But rest assured node internally solves that for you. Quoting code from node 0.12.0:
timer.js > clearTimeout
exports.clearTimeout = function(timer) {
if (timer && (timer[kOnTimeout] || timer._onTimeout)) {
timer[kOnTimeout] = timer._onTimeout = null;
// ...
}
}
On clearing a timeout, Node internally removes the reference to the callback function. So even if the race condition happens, it can do no harm, because those timers will be skipped:
listOnTimeout
if (!first._onTimeout) continue;
Node.js executes in a single thread.
So there cannot be any race conditions and you can reliably cancel the timeout before it triggers.
See also a related discussion (in browsers).
I am talking about a situation where the setTimeout time actually expires and the interpreter starts the process of executing it
Without having looked at Node.js internals, I don't think this is possible. Everything is single-threaded, so the interpreter cannot be "in the process" of doing anything while your code is running.
Your code has to return control before the timeout can be triggered. If you put an infinite loop in your code, the whole system hangs. This is all "cooperative multitasking".
This behavior is defined in the HTML Standard, the fired task starts with:
If the entry for handle in the list of active timers has been cleared, then abort these steps.
Therefore even if the task has been queued already, it'll be aborted.
Whether this applies to Node.js, however, is debatable, as the documentation just states:
The timer functions within Node.js implement a similar API as the timers API provided by Web Browsers but use a different internal implementation that is built around the Node.js Event Loop.

Understanding the Event Loop

I am thinking about it and this is what I came up with:
Let's see this code below:
console.clear();
console.log("a");
setTimeout(function(){console.log("b");},1000);
console.log("c");
setTimeout(function(){console.log("d");},0);
A request comes in, and JS engine starts executing the code above step by step. The first two calls are sync calls. But when it comes to setTimeout method, it becomes an async execution. But JS immediately returns from it and continue executing, which is called Non-Blocking or Async. And it continues working on other etc.
The results of this execution is the following:
a c d b
So basically the second setTimeout got finished first and its callback function gets executed earlier than the first one and that makes sense.
We are talking about single-threaded application here. JS Engine keeps executing this and unless it finishes the first request, it won't go to second one. But the good thing is that it won't wait for blocking operations like setTimeout to resolve so it will be faster because it accepts the new incoming requests.
But my questions arise around the following items:
#1: If we are talking about a single-threaded application, then what mechanism processes setTimeouts while the JS engine accepts more requests and executes them? How does the single thread continue working on other requests? What works on setTimeout while other requests keep coming in and get executed.
#2: If these setTimeout functions get executed behind the scenes while more requests are coming in and being executed, what carries out the async executions behind the scenes? What is this thing that we talk about called the EventLoop?
#3: But shouldn't the whole method be put in the EventLoop so that the whole thing gets executed and the callback method gets called? This is what I understand when talking about callback functions:
function downloadFile(filePath, callback)
{
blah.downloadFile(filePath);
callback();
}
But in this case, how does the JS Engine know if it is an async function so that it can put the callback in the EventLoop? Perhaps something like the async keyword in C# or some sort of an attribute which indicates the method JS Engine will take on is an async method and should be treated accordingly.
#4: But an article says quite contrary to what I was guessing on how things might be working:
The Event Loop is a queue of callback functions. When an async
function executes, the callback function is pushed into the queue. The
JavaScript engine doesn't start processing the event loop until the
code after an async function has executed.
#5: And there is this image here which might be helpful but the first explanation in the image is saying exactly the same thing mentioned in question number 4:
So my question here is to get some clarifications about the items listed above?
1: If we are talking about a single-threaded application, then what processes setTimeouts while JS engine accepts more requests and executes them? Isn't that single thread will continue working on other requests? Then who is going to keep working on setTimeout while other requests keep coming and get executed.
There's only 1 thread in the node process that will actually execute your program's JavaScript. However, within node itself, there are actually several threads handling operation of the event loop mechanism, and this includes a pool of IO threads and a handful of others. The key is the number of these threads does not correspond to the number of concurrent connections being handled like they would in a thread-per-connection concurrency model.
Now about "executing setTimeouts", when you invoke setTimeout, all node does is basically update a data structure of functions to be executed at a time in the future. It basically has a bunch of queues of stuff that needs doing and every "tick" of the event loop it selects one, removes it from the queue, and runs it.
A key thing to understand is that node relies on the OS for most of the heavy lifting. So incoming network requests are actually tracked by the OS itself and when node is ready to handle one it just uses a system call to ask the OS for a network request with data ready to be processed. So much of the IO "work" node does is either "Hey OS, got a network connection with data ready to read?" or "Hey OS, any of my outstanding filesystem calls have data ready?". Based upon its internal algorithm and event loop engine design, node will select one "tick" of JavaScript to execute, run it, then repeat the process all over again. That's what is meant by the event loop. Node is basically at all times determining "what's the next little bit of JavaScript I should run?", then running it. This factors in which IO the OS has completed, and things that have been queued up in JavaScript via calls to setTimeout or process.nextTick.
2: If these setTimeout will get executed behind the scenes while more requests are coming and in and being executed, the thing carry out the async executions behind the scenes is that the one we are talking about EventLoop?
No JavaScript gets executed behind the scenes. All the JavaScript in your program runs front and center, one at a time. What happens behind the scenes is the OS handles IO and node waits for that to be ready and node manages its queue of javascript waiting to execute.
3: How can JS Engine know if it is an async function so that it can put it in the EventLoop?
There is a fixed set of functions in node core that are async because they make system calls and node knows which these are because they have to call the OS or C++. Basically all network and filesystem IO as well as child process interactions will be asynchronous and the ONLY way JavaScript can get node to run something asynchronously is by invoking one of the async functions provided by the node core library. Even if you are using an npm package that defines it's own API, in order to yield the event loop, eventually that npm package's code will call one of node core's async functions and that's when node knows the tick is complete and it can start the event loop algorithm again.
4 The Event Loop is a queue of callback functions. When an async function executes, the callback function is pushed into the queue. The JavaScript engine doesn't start processing the event loop until the code after an async function has executed.
Yes, this is true, but it's misleading. The key thing is the normal pattern is:
//Let's say this code is running in tick 1
fs.readFile("/home/barney/colors.txt", function (error, data) {
//The code inside this callback function will absolutely NOT run in tick 1
//It will run in some tick >= 2
});
//This code will absolutely also run in tick 1
//HOWEVER, typically there's not much else to do here,
//so at some point soon after queueing up some async IO, this tick
//will have nothing useful to do so it will just end because the IO result
//is necessary before anything useful can be done
So yes, you could totally block the event loop by just counting Fibonacci numbers synchronously all in memory all in the same tick, and yes that would totally freeze up your program. It's cooperative concurrency. Every tick of JavaScript must yield the event loop within some reasonable amount of time or the overall architecture fails.
Don't think the host process to be single-threaded, they are not. What is single-threaded is the portion of the host process that execute your javascript code.
Except for background workers, but these complicate the scenario...
So, all your js code run in the same thread, and there's no possibility that you get two different portions of your js code to run concurrently (so, you get not concurrency nigthmare to manage).
The js code that is executing is the last code that the host process picked up from the event loop.
In your code you can basically do two things: run synchronous instructions, and schedule functions to be executed in future, when some events happens.
Here is my mental representation (beware: it's just that, I don't know the browser implementation details!) of your example code:
console.clear(); //exec sync
console.log("a"); //exec sync
setTimeout( //schedule inAWhile to be executed at now +1 s
function inAWhile(){
console.log("b");
},1000);
console.log("c"); //exec sync
setTimeout(
function justNow(){ //schedule justNow to be executed just now
console.log("d");
},0);
While your code is running, another thread in the host process keep track of all system events that are occurring (clicks on UI, files read, networks packets received etc.)
When your code completes, it is removed from the event loop, and the host process return to checking it, to see if there are more code to run. The event loop contains two event handler more: one to be executed now (the justNow function), and another within a second (the inAWhile function).
The host process now try to match all events happened to see if there handlers registered for them.
It found that the event that justNow is waiting for has happened, so it start to run its code. When justNow function exit, it check the event loop another time, searhcing for handlers on events. Supposing that 1 s has passed, it run the inAWhile function, and so on....
The Event Loop has one simple job - to monitor the Call Stack, the Callback Queue and Micro task queue. If the Call Stack is empty, the Event Loop will take the first event from the micro task queue then from the callback queue and will push it to the Call Stack, which effectively runs it. Such an iteration is called a tick in the Event Loop.
As most developers know, that Javascript is single threaded, means two statements in javascript can not be executed in parallel which is correct. Execution happens line by line, which means each javascript statements are synchronous and blocking. But there is a way to run your code asynchronously, if you use setTimeout() function, a Web API given by the browser, which makes sure that your code executes after specified time (in millisecond).
Example:
console.log("Start");
setTimeout(function cbT(){
console.log("Set time out");
},5000);
fetch("http://developerstips.com/").then(function cbF(){
console.log("Call back from developerstips");
});
// Millions of line code
// for example it will take 10000 millisecond to execute
console.log("End");
setTimeout takes a callback function as first parameter, and time in millisecond as second parameter.
After the execution of above statement in browser console it will print
Start
End
Call back from developerstips
Set time out
Note: Your asynchronous code runs after all the synchronous code is done executing.
Understand How the code execution line by line
JS engine execute the 1st line and will print "Start" in console
In the 2nd line it sees the setTimeout function named cbT, and JS engine pushes the cbT function to callBack queue.
After this the pointer will directly jump to line no.7 and there it will see promise and JS engine push the cbF function to microtask queue.
Then it will execute Millions of line code and end it will print "End"
After the main thread end of execution the event loop will first check the micro task queue and then call back queue. In our case it takes cbF function from the micro task queue and pushes it into the call stack then it will pick cbT funcion from the call back queue and push into the call stack.
JavaScript is high-level, single-threaded language, interpreted language. This means that it needs an interpreter which converts the JS code to a machine code. interpreter means engine. V8 engines for chrome and webkit for safari. Every engine contains memory, call stack, event loop, timer, web API, events, etc.
Event loop: microtasks and macrotasks
The event loop concept is very simple. There’s an endless loop, where the JavaScript engine waits for tasks, executes them and then sleeps, waiting for more tasks
Tasks are set – the engine handles them – then waits for more tasks (while sleeping and consuming close to zero CPU). It may happen that a task comes while the engine is busy, then it’s enqueued. The tasks form a queue, so-called “macrotask queue”
Microtasks come solely from our code. They are usually created by promises: an execution of .then/catch/finally handler becomes a microtask. Microtasks are used “under the cover” of await as well, as it’s another form of promise handling. Immediately after every macrotask, the engine executes all tasks from microtask queue, prior to running any other macrotasks or rendering or anything else.

Can JavaScript's setInterval block thread execution?

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 your setInterval() 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 current setInterval() 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?
setInterval and setTimeout are "polite", in that they don't fire when you think they would -- they fire any time the thread is clear, after the point you specify.
As such, the act of scheduling something won't stop something else from running -- it just sets itself to run at the end of the current queue, or at the end of the specified time (whichever is longer).
Two important caveats:
The first would be that setTimeout/setInterval have browser-specific minimums. Frequently, they're around 15ms. So if you request something every 1ms, the browser will actually schedule them to be every browser_min_ms (not a real variable) apart.
The second is that with setInterval, if the script in the callback takes LONGER than the interval, you can run into a trainwreck where the browser will keep queuing up a backlog of intervals.
function doExpensiveOperation () {
var i = 0, l = 20000000;
for (; i < l; i++) {
doDOMStuffTheWrongWay(i);
}
}
setInterval(doExpensiveOperation, 10);
BadTimes+=1;
But for your code specifically, there's nothing inherently wrong with what you're doing.
Like I said, setInterval won't abort anything else from happening, it'll just inject itself into the next available slot.
I would probably recommend that you use setTimeout, for general-purpose stuff, but you're still doing a good job of keeping tabs of the interval and keeping it spaced out.
There may be something else going on, elsewhere in the code -- either in Google's delivery, or in your collection.

Categories