What happens when you wait to resolve a promise in Node - javascript

const fetchPromise = fetch('example.com') // Takes 1 second to resolve
...
... // Do 3 seconds of work
...
const response = await fetchPromise // What happens with the promise between seconds 2-3?
What happens with the promise response before you resolve the promise?
In the example above, what happens with the fetch response in those 2 seconds where your program has items in its call stack, but you don't settle the promise? Does Node have some kind of cache for completed but unresolved promises?

here there is a great reading on the event loop.
In a high level perspective there is a forever running loop listening for events in the form of list of actions and processes them one at a time.
The code you shared above cannot be used globally due to the single threaded design of nodejs. What nodejs does is that every time you call a function it is pushed into the queue and processed. In every tick of the you pop something off the queue and run it or push something new.
In js world no 2 things can run at the same time. If you run a long running js code it blocks the entire system thus your system does not respond to new events since the eventloop is blocked.
That said there is another side of the story when you run all those nonblocking functions they are handled behind the scenes in v8 js engine. Since v8 native code it can make use of things like multiple threads and wait for things to finish or poll things checking whether they are ready and ones things are ready a new message gets inserted back into the js event loop and you get access to the data in js world.
So coming back to your question in an async function when you call await it really just means you yield the execution to the other things waiting in the message queue and once the thing you awaited gets ready it is pushed back to the queue and you continue from where you left of.
There is not really a waiting in the and the point of await is not to block the event loop with a blocking native function and to yield the execution to other things and you async function in the end of the day returns a Promise which only makes sense if you use .then and add a callback to be passed back to js world when the data is ready.

Related

NodeJS setInterval() running parallel to loop using async [duplicate]

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.

Understanding execution of WebAPIs with setTimeout & DOM Api

I have been working with JS for about a year now and I'm still learning it. My question is at the end.
In the first example:
console.log('Start');
setTimeout(()=> console.log('inside callback'), 0);
console.log('End');
outputs
Start
End
inside callback
I understand that even though the timeout is 0, it still had to go to browser WebApi (setTimeout api) and immediately pushed into callback queue waiting for the main thread to be free (which is currently executing console.log('End')). Once the thread is free callback is executed & "inside callback" is printed.
Following this approach, I tried to experiment it with another WebAPI i.e DOM API.
This time, Instead of setTimeout, I used document.querySelectorAll()
console.log('Start');
console.log(document.querySelectorAll('img'))
console.log('End');
Outputs
Start
NodeList(4) [img.bar-sm.-avatar.js-avatar-me, img.bar-sm.avatar.s-avatar--image, img, img]
End
This time we see DOM API output before END is printed.
I know the output but I want to understand the flow behind it.
Why it didn't follow the pattern like setTimeout?
Why didn't the DOM output came after "End" if it was processed on separate thread.
Did it follow the flow below:
document.querySelectorAll -> webAPI -> callback queue -> main thread
Does DOM API have to go though callback queue and wait for main thread to be empty. If so? how come we got consoles in the right order this time unlike with setTimeout
I'm still learning and would appreciate explanation a lot. Please point anything if I misunderstood. Thanks.
The reason is that the document.querySelectorAll is a synchronous method where as the setTimeout is asynchronous.
JS scripts are being executed in the same environment that the DOM lives in, so it is not asynchronous. Asynchronous events are events that generally get sent to another environment (later to be handled by the event loop)
This is part of the concurrency model based on an event loop, which is actually responsible for executing the code, collecting and processing event. The setTimeout function is called with 2 arguments: a message to add to the callback queue, and a time value (optional; defaults to 0). The time value represents the (minimum) delay after which the message will actually be pushed into the queue. If there is no other message in the queue, and the stack is empty, the message is processed right after the delay. However, if there are messages, the setTimeout message will have to wait for other messages to be processed and For this reason, the second argument indicates a minimum time (not a guaranteed time). So, the message 'end' will be written to the console before the message in the callback 'inside callback' gets processed, because the delay is the minimum time required for the runtime to process the request (not a guaranteed time).
document.querySelectorAll is part of scripts that are being executed in the same environment that the DOM lives in, so it is not asynchronous and will be executed immediately.
DOM manipulation is synchronous. having said that, the browser's re-rendering process of the page in response to a DOM update is asynchronous. This can give the illusion of an asynchronous DOM update.
More about the JavaScript event loop - https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

How browser api handles multiple asynchronous functions like setTimeOuts? [duplicate]

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.

Node JS Processor Architecture

I was trying to fetch a solution to my problem regarding node js architecture.
I know node js is single threaded and works on event looping and non-blocking mechanism.
But my problem is how the processor behind it works does it works synchronously and on a priority basis? or it works on multiple requests simultaneously on a single core machine.
Tried to verify this by creating two API's
In 1st API I created a while loop
whereas in the 2nd API I created a response of hello world.
Then I tried to hit both API's 1st and then 2nd but the second API was waiting for the first to end so here the processor was not working on the second API till the first end.
So can I say that the processor of node js will work in synchronous order but not in parallel?
So all the requests will have to wait in a queue for previous requests to complete?
From my perspective, the thing is, answer to this question is not that simple.
1) If we are talking about ExpressJS then yes it works synchronously
2) But let say we are talking about nodeJs built-in executions, like http module it can make calls asynchronously (but it depends upon OS on which NodeJs is running).
Different modules in NodeJs behave differently from synchronous to asynchronous.
NodeJS V8 based VUlibs which are actually C++ based libraries and most of these libraries use threading mechanism. Like crypto module can run execution asynchronously up to some extent.
Your Javascript is single threaded - ALWAYS and it's not pre-emptive either. So an event occurs, some Javascript starts running in response to that event and NO other Javascript can run until that event handler returns control back to the interpreter by returning from the callback that was called to start the event handler.
At that point, another event can fire and run another event handler and again no other Javascript can run until that event handler returns back to the system.
This is true for ALL Javascript that node.js runs.
Ahhh, but not every thing you do in node.js is actually Javascript. Let's suppose you have two simple timers:
console.log("A");
setTimeout(function() {
console.log("B");
fs.readFile("smallfile.txt", function(err, data) {
console.log("C");
});
console.log("H");
}, 1000);
console.log("D");
setTimeout(function() {
console.log("E");
fs.readFile("bigfile.txt", function(err, data) {
console.log("F");
});
console.log("I");
}, 1000);
console.log("G");
This will log in the console
A
D
G
B
H
E
I
C
F
Let's discuss why it will do this.
The A is obvious, it's the first statement.
Then, the code calls setTimeout() which is non-blocking and asynchronous. So, all it does is schedule a timer for some time in the future and then immediately returns. The setTimeout() callback won't be ready to be called for 1000ms so it doesn't get called right now.
So, next after the setTimeout() call returns, we execute the console.log("D");
Then, it executes the next setTimeout() which again just schedules a timer for 1000ms for now and immediately returns.
Then, it executes console.log("G");.
At this point, it returns control back to the JS interpreter and it has nothing else to do for a little while.
Then, approx 1000ms later, the first setTimeout() timer sticks a timer event in the event queue and since the JS interpreter is not running any other Javascript, it grabs that event and runs the JS callback associated with that event. That immediately logs console.log("B");.
Then, it calls fs.readFile("smallfile.txt", ...). This is again non-blocking and asynchronous so all it does is tell the underlying native code fs module implementation to go read all the data from this file and then returns immediately. It then runs console.log("H");. At this point, it's done with this event handler and returns control back to the interpreter.
Meanwhile, the second setTimeout() event is ready so the JS interpreter pulls that event from the event queue and calls the callback associated with it.
That runs console.log("E"); and then calls fs.readFile("bigfile.txt", ...). This is again non-blocking and asynchronous so all it does is tell the underlying native code fs module implementation to go read all the data from this file and then returns immediately. It then runsconsole.log("I");`. At this point, it's done with this event handler and returns control back to the interpreter.
Some time later, the fs.readFile("smallfile.txt", ...) finishes and inserts an event into the event queue. Since the JS interpreter has nothing else to do, it fetches that event and runs the callback associated with it and we see the results of console.log("C"). That is then finished and returns control back to the interpreter.
Some time later, the fs.readFile("bigfile.txt", ...) finishes and inserts an event into the event queue. Since the JS interpreter has nothing else to do, it fetches that event and runs the callback associated with it and we see the results of console.log("F"). That is then finished and returns control back to the interpreter.
At this point everything is done.
Hopefully you can see how asynchronous operations (implemented in native code can run in parallel with Javascript execution using other CPU cores) and they are synchronized with Javascript execution by placing events in the event queue. When the JS interpreter is done running an event handler, it can then look in the event queue for the next event to run, or if nothing there now, go to sleep until the next event is inserted in the event queue.
So, while native code implementations can run in parallel with Javascript, there's still only one thread of Javascript execution that runs at a time and another one can't run until the prior one returns control back to the interpreter by returning from whatever event handler callback start its execution.
Internally in the event loop, there are actually a bunch of different types of queues that are used for different types of events and they have somewhat different priorities relative to one another so it's all a little more complex than I've described it here, but the core concept is an event driven system that runs the Javascript associated with only one event at a time (single threaded) and native code implementations of some operations that can run in a parallel with Javascript execution that are synchronized with Javascript's single thread of execution via the event queue.

where do the browser web api's run in Javascript?

where do the browser web api's run in Javascript like setTimeout ?
Do they run in some other environment or they take the help of javascript single thread ?
They run outside of the JavaScript runtime. Those "Web API's" are executed within the browser's Web API execution space.
setTimeout() for example, is a method of the window object (it can also be invoked as window.setTimeout()). window is not at all part of JavaScript (it's a browser object) and anything you ask the window to do for you is handled outside of the JavaScript runtime and by the browser's other capabilities. The request for the Web API call originates from within the JavaScript environment, but the execution of the API call actually runs outside of it.
This is the very reason that we can have asynchronous behavior in web applications. While the JavaScript runtime (which is a synchronous environment that can only do one thing at a time) is doing its one thing, the browser can be doing something else.
setTimeout(), alert(), navigator.geolocation, XMLHttpRequest are all examples of Web APIs that run outside of the JS engine.
Here are some other Web API's and here is a great video that explains this in the context of timers specifically.
The following series of events occur when the API calls are made:
When the browser makes an API call, the API call is placed in the call stack
API call is placed in the browser's web APIs stack for execution in the background
While the API call is being executed in web APIs background, the render queue tasks are passed to the call stack by the event loop (assuming all tasks in call stack are complete) - this means the render queue is not actively paused hence the browser is not freeze
Once the API call is completed, the results are placed to the callback queue
If the call stack is clear, the results of the API response are placed to the call stack and the API response handler is executed by the call stack
Do comment if you need any clarification
APIs in client-side JavaScript:
To understand how browser APIS works, first, you have to clear concept about execution stack, event loop and message queue
Client-side JavaScript, in particular, has many APIs available to it — these are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code. They generally fall into two categories:
Browser APIs are built into your web browser and are able to expose data from the browser and surrounding computer environment and do useful complex things with it.
For example, the Web Audio API provides JavaScript constructs for manipulating audio in the browser — taking an audio track, altering its volume, applying effects to it, etc. In the background, the browser is actually using some complex lower-level code (e.g. C++ or Rust) to do the actual audio processing. But again, this complexity is abstracted away from you by the API.
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction
<script>
const second = () =>{
console.log("How are you doing");
}
const first = () =>{
console.log("Hi there");
second();
console.log("The End");
}
first();
</script>
Above example is an example of Synchronous JavaScript, where the first function is executed, logs "Hi There!" to the console, calls the second function, which then prints "How are you doing?" to the console,
nd then finally "The end" is logged to the console One instruction after the other in a Synchronous way.
Now let's try by an example with setTimeout which is a web API. considering bellow example
<body>
<script>
const second = () =>{
setTimeout(()=>{
console.log("Async Hi there");
}, 2000)
}
const first = () =>{
console.log("Hi there");
second();
console.log("The End");
}
first();
</script>
</body>
Output:
Now above one involves some Asynchronous JavaScript. Again the first function gets called, logs "Hi There!" to the console, and then calls the second function. Now this function calls the Set Timeout function, which is basically like a timer that will execute the callback function that we passed into it, after 000 milliseconds. However, this will not make the code stop for two seconds, but instead, the function returns, goes back to the first function and logs "The end". Then after the two seconds actually have passed, Async "Hi There!" is logged to the console.
Now, why does the code move on, instead of waiting for the timer to finish?
Well, before I discuss with you how and why this actually works behind the scenes, let me quickly explain to you another example. Suppose we select an image from our DOM and pass it into a Process Large Image function,
that we created. We know that this function is gonna take some time
to process the image. And just like before we don't want the code to have to wait. So we don't want it to stop while the image is processing,
because that would be terrible in some situations. What we do here is to also pass in a Callback function, that we want to be called as soon as the function is done processing. And just like that we have created Asynchronous code.
That is the whole philosophy behind Asynchronous JavaScript. We do not wait for a function to finish its work, and then do something with the result. Instead, we let that function do its job in the background,
so that we can move on with the code execution. We then also pass in a callback function, that will be called as soon as the main function
has done whatever it had to do. We then move on immediately,
so that the code is never blocked. Which means that it can keep processing the code in a Synchronous way, line by line. Because if the code is actually blocked, then nothing really works on the page during that time.
For example you can't click any buttons, or anything like that. So, in summary, we can use callback functions to defer actions into the future.
In order to make our code non-blocking. But how does that actually work
behind the scenes of JavaScript? Well, that's where the Event Loop comes in. the Event Loop is part of the bigger picture of what happens behind the scenes of JavaScript, when we call functions and handle events like DOM events.
Event Loop, as well as the Web APIs, which together with the Execution Stack and the Message Queue make up our JavaScript runtime. This runtime is responsible for how JavaScript works behind the scenes as it executes our code. It's extremely important to understand how all these pieces
fit together in order to execute Asynchronous JavaScript.
Let's now take a look at how the code from the last example
is executed inside our JavaScript engine, line by line.
It starts by calling the first function, and as we already know,
an Execution Context for that function is put on top of the Execution Stack, which can also be called the Call Stack.
In the next line of code, the console dot log function is called and a new Execution Context is created and the text is logged to the console.
Then the function returns and the Execution Context pops off the stack.00
Moving on to the second function, a new Execution Context is created
and in the next line the Set Timeout function is called. Which causes yet another Execution Context to be created.
Now, before we move on, where does this Set Timeout function actually come from? It's part of something called the Web APIs. Which actually live outside the JavaScript engine itself. Stuff like DOM manipulation methods, Set Timeout, HTTP requests for AJAX, geolocation, local storage and tons of other things, actually live outside of the JavaScript engine
We just have access to the because they are also in a JavaScript runtime
This is exactly where the time will keep running for two seconds, asynchronously of course so that our code can keep running without being blocked.
When we call the Set Timeout function the timer is created, together of course with our callback function Right inside the Web APIs environment.
And there it keeps sitting unti it finishes its work all in an Asynchronous way.
The callback function is not called right not but instead it stays attached to the timer until it finishe
And since the timer keeps working basically in the background, we don't have to wait and can keep executing our code. Next up, the Set Timeout function returns, pops off the stack and so does the Execution Context of the second function Which now returns as well and we are back to the initial first function. Now we just log the end to the console
and we give ourselves a new Execution Context, print the text to the console and pop the text off again.
Next the function returns and we are back to our original state
Right now we have executed all our code in a Synchronous way,and have the timer run Asynchronously in the background. Let's suppose that our two seconds have passe and the timer disappear. But what happens to our callback function no Well, it simply moves to the Message Queue
where it waits to be execute as soon as the Execution Stack is empty
This is exactly what happens with DOM events.
In the case of DOM events our event listeners sit in the Web APIs environment, waiting for a certain event to happen And as soon as that event then happen then the callback function is placed on a Message Queue
ready to be execute.
Alright, so how are these callback function in the Message Queue executed
And that's where, finally, the Event Loop comes in. The job of the Event Loop is to constantly monitor the Message Queue and the Execution Stack,
and to push the first callback function in line onto the Execution Stack, as soon as the stack is empty. In our example here, right now the stack is empty, right And we have one callback waiting to be execute
And the event loop takes the callback and pushes it onto the stack
where a new Execution Context is created for that function.
That's what the event loop does. Inside that callback function now,
we simply run the log function, which logs Async "Hi There!" to the console. Then the context pops off the stack and we're done! Now if there were some callbacks waiting right now like data coming back from an AJAX request or the handler of a DOM even then the Event Loop would continue pushing them onto the stack until all of them were processed.

Categories

Resources