What's happening with that piece of code
var start = new Date();
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func1:',end - start, 'ms');
}, 500);
setTimeout(function() {
var end = new Date();
console.log('Time elapsed with func2:',end - start, 'ms');
}, 250);
while (new Date() - start < 1000) {}
Logs:
Time elapsed with func2: 1001 ms
Time elapsed with func1: 1017 ms
I was expected that func1 will be fire first because it's the first event to be added into the event queue. Then, due to the single thread nature of JS, wait until func1 returns and then executes the next event in the queue which is func2.
So, what's happening?
First off setTimeout() is asynchronous and non-blocking. That means when you call it, all it does is register the new timer and then immediately returns. So, when your code runs, it will follow these steps:
You register the func1 timer for 500ms.
You register the func2 timer for 250ms.
Each of the timers is added to a sorted data structure inside the timer portion of the event loop so it's easy for the event loop to know and check which timer is next to execute.
You start the while spin loop. That loop runs for about 1000ms.
When the while spin loop finishes, the Javascript interpreter gets to go back to the event loop to check if there is anything else to do. One of the things it checks (one of the phases of the event loop) is to see if there are any timers ready to run. It checks the head of the timer list and sees that its time has already passed by (meaning it is past time for it to run). So, it grabs the callback associated with that func2 timer and executes it. The func2 timer is at the start of the list because it's has the earliest time associated with it.
When that callback finishes executing, the JS interpreter again returns control back to the event loop where it again checks if there isn't anything else to do. It will find that the func1 timer is now at the head of the list and past its time to run so it grabs the callback associated with that timer and executes it.
And thus, you get the output you see with the func2 callback executing as soon as the while spin loop is done, then the func1 callback executing after that.
Note, these timers are purely event driven. There is no interrupting of the currently executing Javascript to execute a timer. For this reason, timers in Javascript are a best effort kind of implementation. If you set a timer for 1000ms from now, then the callback associated with that timer will run no sooner than 1000ms and could be later than that if the JS interpreter was busy at the appointed time for that timer.
The one aspect of timers that is missing from the above description (because it doesn't occur in your situation) is what happens if you don't have the while() spin loop. In that case, your code returns control back to the event loop right after configuring both timers, the event loop checks to see if any timers are ready to run, but none are yet ready to run. It will then sleep until something wakes it up again, but not sleep longer than the time to the next currently set timer.
No, wait. It won't add your timeout call to the event queue. It's handled by the webapi by the browser and then when your timeout kicks-off then it'll add your function to the event queue.
Whatch this: https://www.youtube.com/watch?v=8aGhZQkoFbQ#t=13m
(From 13:00)
Javascript is single-threaded. Even though there are asynchronous callbacks, they are not con-current.
This means, the code inside(setTimeout(fn, num)) only gets called once the entire code has finished execution. Therefore, if num parameter = 5000. This means, the function setTimeout(...) will run: after the entire code (i.e. not just the code up to the point when setTimeout is called but everything) has finished executing + 5 seconds. Hope this helps.
Related
setTimeout(function(){
console.log("m");
}, 0);
console.log("s");
Why does this code print "s" before "m", even if the setTimeout callback is supposed to wait for 0 ms?
A browser or node.js always run a single threaded event loop to run your code. On the first run it will always run your synchronous code but may also que up asynchronous events that will call back later. Thats why we call the function here callback function it will be called later.
setTimeout is a microtask.
That means the function that you see isnt gona executed immedantly, it is gonna first queued up and will be executed within the next event loop.
Also a sidefact: 0 ms just means it will minimum wait 0 ms not exact 0
When you create a promise, or call an async function, or set a timeout for 0 milliseconds, the function is immediately queued into the Javascript event loop. Essentially, the function is added to a queue of functions to call, and once the javascript interpreter has nothing to do it'll start calling those functions. So, when you set a timeout for 0 milliseconds, it queues the console.log("m"), then calls the console.log("s"), then it has nothing to do so it finishes the queued console.log("m"), which is why it's out of order.
it just because JS is single-threaded and event loop works that way.
setTimeout has written in a way that it will send you function or whatever you want to do in a callback queue.
and then move forward to the next line, once next line executed it will not run your setTimeout part, or in other words, it will not process the setTimeout part until the stack is not empty.
so this is your code, and it will execute like this.
setTimeout(function () {
console.log("m");
} , 0)
console.log('s');
the first line will execute and it will send the inner part of setTimeout to callback queue and move to the 2nd line.
while 2nd line is executing the setTimeout part will wait till the stack is not emplty and as soon as 2nd line finishes execution,
the setTimeout part will execute,
maybe it's confusing by words, let's see this in action. I bet you can not get a better example than this to understand it, it's explained in the best way by Philip robert.
because JS code goes in order one by one. When you specifying setTimeout to 0 is still waiting, in C++ lang this would be something like this 0.000000245ms, and JS runs often on C++/C browser.
try this simple example
for (let x = 0; x < 500; x++) {
setTimeout(() => console.log(x), 0);
}
console.log('hello');
I was in an awkward situation,
I am working with pure JavaScript for almost 3 years, and I know that JavaScript is single-threaded language,
and that you can simulate asynchronous execution using setInterval and setTimeout functions,
but when I thought about how they can work I couldn't clearly understand it.
So how these functions affect execution context?
I suppose that in specific time runs only one part of the code and after it switches to
another part. If so, then would a lot of setInterval or setTimeout
calls affect performance?
Javascript is singled-threaded but the browser is not. The browser has at least three threads: Javascript engine thread, UI thread, and timing thread, where the timing of setTimeout and setInterval are done by the timing thread.
When calling setTimeout or setInterval, a timer thread in the browser starts counting down and when time up puts the callback function in javascript thread's execution stack. The callback function is not executed before other functions above it in the stack finishes. So if there are other time-consuming functions being executed when time up, the callback of setTimeout will not finish in time.
How setTimeout / setInterval work's in JavaScript
Browser has API for Timer function just like API for event ex.
'click'
'scroll'
Assume that you have following code in your application
function listener(){
...
}
setTimeout(listener, 300)
function foo(){
for(var i = 0; i < 10000; i++){
console.log(i)
}
}
foo()
![See How Function Execution work's in javascript ][1]
[1]: https://i.stack.imgur.com/j6M6b.png
At this point as per our code we wrote above our call stack will look like
Call Stack -> foo
And let's assume that foo will take 1s to complete it's execution, as we already defined 1 timeout in our code and we are running it before "foo" complete's it's execution i.e at 300ms
What will happen then ?
Does javascript stop executing foo and start executing setTimeout ?
No
As we already know javascript is single threaded so it has to complete execution of foo before moving ahead, but how does browser ensure that after execution of foo the "setTimeout" will execute ?
Here javascript magic comes into picture
When 300ms is expired, the browser's "Timer API" kicks in and put the timeout handler into "Message Queue".
At this point "Message Queue" in above image will look like
Message Queue -> setTimout:listner
And
Call Stack -> foo
And when "Call Stack" becomes empty i.e foo completes it's execution the "Event Loop" as shown in the image will take the message from message queue and push it into stack
The only job of "Event Loop" is when "Call Stack" becomes empty and "Message Queue" has entry in it then dequeue the message form "Message Queue" and push it into "Call Stack"
At this point Message Queue in above image will look like
Message Queue ->
And
Call Stack -> listener
And that's how setTimeout and setInterval works, even though we specify 300 ms in the setTimeout it will execute after "foo" completes it's execution in this case i.e after 1s.
And that's why timer specified in setTimeout/setInterval indicates "Minimum Time" delay for execution of function.
Javascript is single threaded but browser is not.
There is 1 stack where function and statements get executed.
there is 1 queue where function are queued to be executed.
there are web APIs which can hold the function for particular time, defined in setTimeout and setInterval in event table.
when javascript engine execute js file line by line, if it finds a line as statement or function call it load it on stack and execute but if it is setTimeout or setInterval call,
then function handler associated with setTimeout or setInterval is taken out by TIME API (one of web API of browser)and hold it for that time.
Once this time is over, Time Api put that function at end of execution queue.
Now Execution of that function depends on other functions calls which are ahead of in queue.
Note: this function call is called upon window object.
setTimeout(function () {console.log(this)}, 300)
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
JavaScript is a single-threaded scripting language, so it can execute one piece of code at a time (due to its single-threaded nature) each of these blocks of code is “blocking” the progress of other asynchronous events. This means that when an asynchronous event occurs (like a mouse click, a timer firing, or an XMLHttpRequest completing) it gets queued up to be executed later.
setTimeout()
when you use setTimeout() it will execute only when its turn comes in a queue, if an earlier event (of setTimeout) blocks due to some reason setTimeout can be delayed than the specified time in setTimeout() function. during the execution of setTimeout callback function, if any event occurs(e.g click event),it gets queued up to be executed later.
setTimeout(function(){
/* Some long block of code... */
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){
/* Some long block of code... */
}, 10);
setInterval()
Similar to setTimeout but continually calls the function (with a
delay every time) until it is canceled.
setTimeout code will always have at least a 10ms delay after the
previous callback execution (it may end up being more, but never
less) whereas the setInterval will attempt to execute a callback
every 10ms regardless of when the last callback was executed.
If a timer is blocked from immediately executing it will be delayed
until the next possible point of execution (which will be longer than
the desired delay). Intervals may execute back-to-back with no delay
if they take long enough to execute (longer than the specified
delay).
Just a note in regards to my experience, If you are going to use setTimeout(), the function will always be delayed (and I mean executed later) or executed after further code which is not 'timeouted'. This may happen even with functions which have delay = 0 and is caused by Event Loop.
See example below:
setTimeout(function() {
console.log('Second');
}, 0)
console.log('First');
I use while(true) to simulate the js thread blocking as below
setInterval(() => {
console.log(new Date(), 'interval');
}, 500);
while (true) {
console.log(new Date(), 'while true');
}
In the above code, we cannot see interval printed on the terminal because the call stack busy at executing what's in the while(true).
But I can see interval in the below code by adding one more await in the while(true).
main();
async function main() {
setInterval(() => {
console.log(new Date(), 'interval');
}, 500);
while (true) {
console.log(new Date(), 'while true');
await wait();
}
function wait() {
return new Promise(ok => setTimeout(ok, 0));
}
}
Why adding one await in the while(true) would make js main thread have spare time to execute the interval ?
I usually use this image while thinking of async behaviour in js. I'm thinking the call stack is full of what's in the while(true) no matter we put a await or not.
event loop image from
https://medium.com/#swarajgandhi/what-the-heck-is-the-event-loop-anyway-fc5a687a9577
javsacript / node.js await one more task makes it unblock?
It depends upon what the task is that you're awaiting.
Why adding one await in the while(true) would make js main thread have spare time to execute the interval ?
Here's a simplified sequence of steps that happens with this loop:
while (true) {
console.log(new Date(), 'while true');
await wait();
}
Log the date
call wait()
When executing wait() call setTimeout(ok, 0)
Return unresolved promise from wait().
await that unresolved promise.
Your while loop is now suspended until that promise resolves.
Control goes back toward the event loop upon the function suspension at the await.
The first thing that is checked is a few higher priority things like the promise job queue. Nope, nothing there yet.
OK, go back to the main event loop. This main event loop has multiple steps in its cycleand one of those steps is for timers.
When the event loop gets to the timer stage, see what the oldest timer-related event is and call its callback. Hmmm, if there was already an overdue setInterval() timer waiting to run, it will get to run. After it runs, check for any other pending timers and run them.
If there's no overdue setInterval() waiting to run, then the setTimeout(ok, 0) should now be ready the run. The event loop calls its callback which resolves the promise we created earlier.
Now, there is something in the promise job queue so service that. This will resume the main function call on the await where it left off in step #6, and the while loop gets to run another cycle (starting at #1).
Because of step #10, you can see that at some point, there will be an overdue setInterval() waiting to run and it will be in line in front of the most recent setTimeout(ok, 0) so it will get to run. After it runs, the next setTimeout(ok, 0) will get its turn to run.
Thus, you get to see the setInterval() results when you await something that is only resolved when a setTimeout() fires.
So, put even simpler. The setInterval() timer and the setTimeout() timer are served by the same part of the event loop. So, the same code in the event loop that allows your setTimeout() to run which will resolve the promise you are awaiting also allows the setInterval() timer to run. So, when you await the promise that gets resolved by a setTimeout() you're making your code wait until the event loop gets to the part where it serves timers and while it's doing that, it's going to serve any setInterval() firing that was already waiting before you registered your setTimeout(). It won't serve only your setTimeout() without also serving any already waiting setInterval().
So, it's not so much about "spare time" in the event loop, but about ordering in the event loop. A setInterval() that is already overdue will get served by the event loop before your setTimeout(ok, 0). So, the promise in your wait() function won't get resolved until after any setInterval() that was already waiting to run gets to run, thus allowing them to interleave and both get to run.
As a test and a puzzle for further understanding, try changing to this:
function wait() {
return Promise.resolve();
}
This will return an immediately resolved promise which will not let the setInterval() get a chance to run because resolved promises get served before the main event loop that handles timers like setInterval(). So, you never allow the event loop to get around to serving timers as you starve it by constantly giving it a resolved promise to serve.
Note, you will generally not want to program this way (with a loop on an already resolved promise) because you are starving other parts of the event loop. This was just a demo for illustration purposes.
what could be the reason for a setTimeout to wait 2-4 times as long as configured to be executed?
var TIMEOUT = 700;
console.log("TIMEOUT", TIMEOUT);
var preTimeout = new Date();
setTimeout(function() {
console.log("timeout took:", new Date() - preTimeout);
}, TIMEOUT);
This results in timeout took: from 1200-4000 on a website.
setTimeout() doesn't mean execute the code after exactly N milliseconds. It rather means, don't execute the code for at least N milliseconds.
The asynchronous code such as the setTimeout() callback is put on an event loop queue until all syncrhonous code finishes executing, and then it's run. This includes any async code that gets run in the queue before the timeout period. Your callback can run only after all those are done.
Here's a small demo to show this using synchronous while loop:
https://jsfiddle.net/foxbunny/1a9rckdq/
Code like the one in the demo is what you'll hear people referring to as 'blocking'. This is because it blocks the event loop queue.
I've also written a somewhat long article on the topic if you want a throrough overview.
If the callback for a setTimeout invocation is added to the job queue (for example, if it is next on the job queue), and a clearTimeout is called on the current tick of the event loop, supplying the id of the original setTimeout invocation. Will the setTimeout callback on the job queue be run?
Or does the runtime magically remove the callback from the job queue?
No, it won't run; it will be queued and then subsequently aborted. The specificiation goes through a number of steps when you call setTimeout, one of which (after the minimum timeout, plus and user-agent padded timeouts etc) is eventually:
Queue the task task.
This appears to happen regardless of whether or not the handle that was returned in step 10 has been cleared - ie a call to setTimeout will always result in something being enqueued.
When you call clearTimeout, it:
must clear the entry identified as handle from the list of active timers
ie it doesn't directly affect the process already kicked off in the call to setTimeout. Note however that further up that process, task has been defined as:
Let task be a task that runs the following substeps:
If the entry for handle in the list of active timers has been cleared, then abort this task's substeps.
So when the task begins executing, it will first check if the handle has been cleared.
No, it won't be ran.
I don't know which source should be used to back it up officially, but it's at least easy to try for yourself.
function f() {
var t1 = setTimeout(function() { console.log("YES"); }, 2000);
sleep(3000);
clearTimeout(t1);
console.log("NO");
}