Does setTimeout get added to the call stack? - javascript

I've been learning about setTimeout and synchronous versus asynchronous code, I was watching a tutorial video where they showed various functions being called and added to the call stack, e.g. a function to simply add 2 numbers.
However for setTimeout they didn't show that when this was invoked that it was being added to the call stack, I understand that this fires up a web API and that the callback is added to a queue but I'm curious if in the moment that setTimeout is being executed by the JS engine, is it added to the call stack or not?

in the moment that setTimeout is being executed by the JS engine, is it added to the call stack or not?
It is. And it is popped from the call stack as soon as the callback is registered, so this hardly takes any time.
When the given delay has passed, the callback will be queued. Then when the call stack is empty, JS will process the event queue, and the callback will be called. Also this callback will be added to the call stack.
Just note that setTimeout and the callback will not be added to the call stack cumulative. It is guaranteed that the call stack will be emptied first before the callback will be pushed unto it.

Yes, after the time set in timeout passes, the callback is pushed to the call stack & executed.
Actually, the only way for a JS function to execute is to pass through the call stack.
Here is a good visualization tool called loupe by Philip Roberts that may help in understanding the call stack & things related to it.

setTimeout would be pushed to the call stack and then popped. When it is popped, it is sent to a browser API (if the code is executed in the browser). The API waits till the specified time is done and the callback is sent to the event queue. When the call stack is empty, the event loop will take the callback from the event queue (assuming it was next in line in the queue) and put it to the stack when it then gets executed.

Related

How "call stack" and "event loop" interact or work together?

I am little bit confused about the architecture of Node.js
As i know, in browser runtime environment event loop continuously check call stack empty or not, if empty then push callback from callback queue or microtask queue into call stack.
Nodejs Architecure's image
But in nodejs, event loop checks it is blocking operation or not.
My question is that,
Suppose I have a function in which first 10 lines are synchronous code on 11th line there is some asynchronous or blocking function.
Then as I know (please correct me if i'm wrong), function should first go into callstack and run first 10 lines and when callstack reaches on 11th line then it will go some into another queues.
But as i attached an image link in that it is not clear, what is the flow of code execution between callstack & eventloop.
As i know, in browser runtime environment event loop continuously check call stack empty or not, if empty then push callback from callback queue or microtask queue into call stack.
First off, there's no continuously checking the call stack. The event loop itself is at the root of the call stack. So, when user code finishes executing and returns, that return from the last bit of Javascript that was executing goes back to the event loop where it can examine the various queues and determine which event to process next.
My question is that, Suppose I have a function in which first 10 lines are synchronous code on 11th line there is some asynchronous or blocking function. Then as I know (please correct me if i'm wrong), function should first go into callstack and run first 10 lines and when callstack reaches on 11th line then it will go some into another queues.
An asynchronous function does NOT block. It starts some operation and then code just keeps on executing. So, as an example, if you call fs.readFile() or fs.promises.readFile() in nodejs, those function calls initiate the operation and then immediately return and the line of code right after that executes. As this code after your call to .readFile() finishes executing, it will eventually return control back to the event loop where, some time in the future, that .readFile() function will complete and insert an event in an event queue that the event loop can then process.
what is the flow of code execution between callstack & eventloop.
The call stack controls a given chunk of Javascript executing. When a function call is made, the place that execution should continue at when that function returns is pushed into the callstack. It's just a mechanism for handling function calls. Unlike other languages, variables scoped within a function are not put on the stack because those type of scope variables in Javascript can have a different lifetime than the execution of the function. They are garbage collected instead. So, the callstack in Javascript is just return locations from function calls.
Because nodejs runs your Javascript as a single thread, the event loop does not get to execute any waiting events until a given chunk of Javascript finishes executing, the call stack is then empty and control returns back to the event loop where it can then start a new chunk of Javascript executing to process the next event.
So, the callstack facilitates running a chunk of Javascript. Only when the callstack is empty and control returns back to the event loop can the next event waiting to be processed get run. The two do very different things.

Can someone explain JS Event Loop?

So I kind of understand the JS event loop, but still have a few questions. Here is my scenario and a few questions.
So let's say I have these functions:
function1 - reads an absolute huge file.
function2 - console.log("Hey");
function3 - console.log("What's up");
The way I am understanding this, and correct me if I'm wrong, what would happen is that the function1, function2, and function3, would be added to the queue. Then function1 would be added to the call stack followed by the next two functions.
Now the part where I'm confused is because the first function is going to take an extremely long time what happens to it? Does it get pushed somewhere else so that the next two functions are executed? I think the answer to this is that the only way it gets pushed somewhere else so that you can continue running is to make it an asynchronous function. And the way you make it a asynchronous function is either by using a callback function or promises. If this is the case how does it know that this is a asynchronous function? And where does it get pushed to so that the other two functions can be executed since they are relatively simple?
I think I answered the question myself but I keep confusing myself so if somebody could explain in extremely simple terms that would be great and sorry for the extremely stupid question.
Ordinary function calls are not pushed on the event queue, they're just executed synchronously.
Certain built-in functions initiate asynchronous operations. For instance, setTimeout() creates a timer that will execute the function asynchronously at a future time. fetch() starts an AJAX request, and returns a promise that will resolve when the response is received. addEventListener() creates a listener that will call the function when the specified event occurs on an element.
In all these cases, what effectively happens is that the callback function is added to the event queue when the corresponding condition is reached.
When one of these functions is called, it runs to completion. When the function returns, the event loop pulls the next item off the event queue and runs its callback, and so on.
If the event queue is empty, the event loop just idles until something is added. So when you're just starting at a simple web page, nothing may happen until you click on something that has an event listener, then its listener function will run.
In interactive applications like web pages, we try to avoid writing functions that take a long time to run to completion, because it blocks the user interface (other asynchronous actions can't interrupt it). So if you're going to read a large file, you use an API that reads it incrementally, calling an event listener for each block. That will allow other functions to run between processing of each block.
There's nothing specific that identifies asynchronous functions, it's just part of the definition of each function. You can't say that any function that has a callback argument is asynchronous, because functions like Array.forEach() are synchronous. And promises don't make something asychronous -- you can create a promise that resolves synchronously, although there's not usually a point to it (but you might do this as a stub when the caller expects a promise in the general case). The keyword async before a function definition just wraps its return value in a promise, it doesn't actually make it run asynchronously.

What is the behaviour of callback execution in C# (assuming configure await is not set to false and assuming there is synchronization context)?

In Javascript, the callback (of the awaited async function) runs only when the call stack is empty. If there are multiple callbacks, then they are queued (in the event loop queue) such that only 1 callback runs in its entirety before the next callback gets change to run.
In case of C# (assuming ConfigureAwait is not set to false - that is - the callabck will run in the same thread; also assuming there is syncronization context [winforms]):
Does the callback run immediately without waiting for call stack to be empty?
Suppose there are multiple callbacks queued, then while 1 callback is running, and another callback is ready for execution, then does the running callback suspend while the new callback wants to run? Or is it sequential?
The answer is that it depends on the current SynchronizationContext and, if that is null, the current TaskScheduler.
When the awaited Task completes, and you have configured the Awaitable to capture the context and recover on it, then almost certainly that continuation cannot continue immediately (the thread is likely busy executing something else). All that can be done is to schedule the continuation for later execution on the current SynchronizationContext, which is done by calling SynchronizationContext.Post().
How this Post method is implemented depends on the SynchronizationContext (which is abstract). If you are using WPF, the SynchronizationContext is a DispatcherSynchronizationContext. There, Post is implemented by a call to Dispatcher.BeginInvoke() with DispatcherPriority.Normal.
In other words, your continuation gets queued on the dispatcher for later execution with normal priority. Other delegates may have higher priority (e.g. DispatcherPriority.Input), but eventually your delegate gets executed on the dispatcher.
Two things to notice:
BeginInvoke simply queues your delegate. It does not execute it right away. In other words, queuing your delegate is really fast.
The above explanation should illustrate why async-await is just syntactic sugar. You could achieve all these calls yourself, but the compiler does it for you, making your code flow more naturally.

Clarification on synchronous and asynchronous callbacks in javascript

iam currently working through the concept of callbacks and asynchronous programming in javascript. For that i read the corresponding chapters in the book "JavaScript" written by Philip Ackermann (ISBN:937-3-8362-5696-4).
But i have problems understanding the term asynchronous applied to callbacks used in examples of the book.
My current understand is that i can write synchronous callbacks like this:
function synchronousCallback(text, callback) {
//other code
callback(text);
}
synchronousCallback("End of function", console.log);
In the above example the callback is in my opinion only a nested function call. Nothing more.
But in a similar example of the book the author calls such a function asynchronous. See below the exact example of the book:
function asyncFunction(callbackFunction) {
//some code
console.log('Before callback');
callbackFunction();
console.log('After callback');
//some more code
}
function callbackFunction() {
console.log('called callback');
}
asyncFunction(callbackFunction);
My understanding of the code execution is that this callback would be executed as soon as the 'other code' is finished. The callback would not be added to the callback queue of the javascript engine and therefore be synchronous/blocking.
In my point of view a callback is asynchronous when used with setTimeout() or setInterval().
Maybe the example in the book is misleading or i misunderstood the term asynchronous in that case or i didnt not understand the execution order of such a callback scenario correctly.
Thanks for any help or clarification
There's nothing asynchronous about the example you gave.
Callbacks are asynchronous if the JavaScript event loop carries on running the rest of your program until an external factor (time passing in the case of setTimeout) triggers the callback.
Either the book is wrong, or you've not adequately expressed everything in the "similar" example it gave.
I have already mentioned the difference between synchronous and asynchronous behavior in JavaScript with this answer to your other question. I'll try to give you more details with this answer.
There, I recommended that you watch couple of talks about the subject. A talk by Philip Roberts, another talk by Jake Archibald or Jake's blog which explains the same. I'll try to summarize all of that.
All JavaScript code is synchronous and executes within a single thread. This means that there's one call stack and it can do one thing at a time. To better understand JavaScript runtime, please take a look at this image taken from MDN.
Let's try to go through your second example to see what's going on. When asyncFunction() gets called, it is pushed to stack (Jake calls them tasks, but based on MDN image, they are frames). Then, console.log('Before callback') is called and it gets pushed to stack on top of the current frame. So now, there's console.log on top and asyncFunction below.
console.log logs that string to console. Then, it's removed (popped) of the stack. asyncFunction is now on top of the stack. Now, callbackFunction() gets called and it is pushed to the stack, which then calls console.log('called callback') which also gets pushed to the stack.
Now, there are three functions on the stack: asyncFunction at the bottom, callbackFunction and console.log at top. When console.log finishes its job, it gets popped off the stack and now callbackFunction is also finished and that one also gets popped off the stack. Now, console.log('After callback') is called, pushed to the stack and popped after execution, which means that asyncFunction is finished and can be popped off the stack.
This is where all ends, the stack is empty, no more frames on it. Based on this and talks from the link above, there's nothing asynchronous in this example. A step by step is made by JS runtime and no asynchronous jumps are made here. But, how do we achieve concurrency in JS and do we need it? To quote Philip:
The reason we can do things concurrently is that the browser is more than just the runtime.
This is the reason why we can use setTimeout(() => { doSomething(); }, 5000) which would wait for 5(000 thousand milli)seconds without blocking (freezing) web page during that time. What happens when setTimeout is called? The browser starts another thread which runs in parallel. The thread's job is to only wait for 5 seconds. But, now it gets interesting what happens when the time's up.
To prevent concurrent modifications which might lead to unexpected behaviors, browsers have a queue mechanism. This allows the thread created by setTimeout to post a message to it and the message is, in this case, a function passed to setTimeout that will get executed once the message is processed.
But when are the messages processed? Well, just after no frames (tasks) are stacked. This means that messages are waiting for stack to get cleared after all frames are finished so that they can be processed. Messages are processed one at a time per one loop. Once message is taken as task it becomes regular JS code which gets executed on the same thread with the same rules for pushing and popping stack. Any other potential messages that are queued in the meantime must wait for the current message/frame to be processed.
setTimeout and setInterval are all parts of WebAPIs. Many (if not all) of them have asynchronous callbacks, and some examples include: DOM events, XHR events, Fetch events, Web workers, Web sockets, Promises, MutationObserver callbacks and so on. The last two (Promises and MutationObservers) schedule tasks on a different queue (microtask queue), but it's still asynchronous.
The difference between messages that are set to microtask queue and regular (or macrotask) queue is that the messages from macrotask queues are taken one at a time per event loop (which means that the whole loop needs to go around between two messages are processed), while messages from microtask queues are taken immediately after the stack is cleared. This means that they have higher priority than the ones on the macrotask queues. For more info, please watch/read Jake's talk/blog.
In my point of view a callback is asynchronous when used with setTimeout() or setInterval().
Yes, but not only with setTimeout() or setInterval(). If you set your callback to XMLHttpRequest's onreadystatechange function, it will be called asynchronously all the same.
Please note that there may be other APIs that require different set of function parameters than the ones from these examples - in fact, these examples aren't using function parameters at all.

Javascript event loop clarification

I keep seeing explanations of the "Javascript Event Loop" (ie: browser JS runtime event loop) that don't seem plausible to me, and I'm hoping someone can provide some authoritative clarification.
My base asssumption is that the JS event loop is just like event loops we've been working with in UI frameworks for decades, something like:
// [... some initialization ...]
// The Event Loop
while (true) {
if (! EventQueue.isEmpty()) {
event = EventQueue.pop_oldest_item();
event.callback(event [or some other kind of args]);
}
// [... defer to other non-JS tasks...]
}
But I keep seeing explanations (see below for examples) like this:
The event loop:
Checks whether the (Javascript) call stack is empty.
Checks whether the callback queue [AKA EventQueue] is empty.
If call stack is empty and callback queue is NOT empty, then:
a. Dequeue oldest callback queue item.
b. Push that callback function onto the call stack (and no mention is made of calling that function.)
Keep looping.
This obviously vaguely follows my assumed model above, but with two key and troubling differences:
A. Why would the event loop need to check that that the JS call stack is empty? Surely every time around the loop the call stack will be in the same state (whether that's completely "empty" is beside the point -- it doesn't need "checking"). Whatever function was called last time around will have returned, restoring the stack. So that part makes no sense.
B. Why would the event loop "push the callback onto the JS stack"? Shouldn't the event loop just call the function, thereby creating a legitimate stack frame, and a way to return from the function, not to mention actually executing the function?
So I would appreciate a clarification that addresses these explanations and why they are actually correct, or bolsters my strong suspicion that they are incorrect.
Example sources of these event loop explanations:
Philip Roberts: What the heck is the event loop anyway? At 14:00
https://youtu.be/8aGhZQkoFbQ?t=839
Typescript High Performance (book) page 83.
What is the Javascript event loop?
http://altitudelabs.com/blog/what-is-the-javascript-event-loop/
Understanding Javascript Function Executions - Call Stack, Event Loop, Tasks & more
https://medium.com/#gaurav.pandvia/understanding-javascript-function-executions-tasks-event-loop-call-stack-more-part-1-5683dea1f5ec
This is my answer to your question:
JavaScript behaves in a single threaded and synchronous manner, so the event callback function will be executed after Global Execution Context pops off the execution stack. All the event will be added into the what called event queue.
After global execution context finish all the execution, JS engine will keep checking if there exist any event inside the event queue. If JS engine sees there is an event, then it will create a new execution context for callback function and push it on the execution stack.
In JS, each time you invoke a function, JS engine will create an execute context, which creates a private scope where anything declared inside of the function can not be directly accessed from outside the current function scope, and pushes on the top of the execution context stack. After the function finish executing, the execution context will be popped off.
Because of the asynchronous nature of some functions that are executed in the call stack (event handlers, setTimeout, http requests) messages (callbacks) from these operations can be added to the message queue at any time. This can happen while the main thread is still running functions in the call stack so the event loop needs to check to see if it is empty or not. Once empty then it will pull the next message from the message queue and throw it into the call stack. This cycle constitutes the essence of the event loop.
I made a video presentation that explains and demonstrates this process:
https://www.youtube.com/watch?v=4xsvn6VUTwQ

Categories