In the last video you got started with a synchronous no to j s development and even with a simple script
like this one we ended up asking a lot of questions and not getting a lot of answers.
The goal of this video is to explore the internals of node and V eight to see how asynchronous scripts
actually execute that's going to give us answers to questions like why does this two second set time
out delay not prevent the rest of the program from running and why does a zero second delay caused this
function to run and print zero second timer after stopping prints.
Which is exactly what we're seeing down below.
So the goal is to explore the internals to get a better understanding of what exactly is happening.
I actually recommend watching this video twice.
Watch it once right now then watch it once we're done building the weather application and you have
a lot more exposure to various forms of asynchronous programming that's going to really reinforce and
reinstall exactly what's happening behind the scenes.
Now we're gonna start off with a little visualization working through how node would execute a synchronous
example.
Then we'll explore exactly how node would execute this script line by line.
I'm excited to get to that and so let's jump right in right here we have our first of three examples.
Now even very simple synchronous example like this one there is still quite a bit going on.
So let's take a quick moment to break down what we're seeing here at the top left.
We have the node file that's executing.
So this is our very simple script.
We create a couple of variables and we print a message to the screen down below.
We have the terminal output for that script.
So as these script prints something that'll show up down here on the right hand side.
We have all of the internals that are running behind the scenes in both node and v 8.
We have our call stack.
We have the node API is our callback queue and our event loop all of which work in tandem to get our
asynchronous programs running.
Now for a simple synchronous examples like this one the only of these four we need to worry about is
the call stack.
So let's take a moment to start there.
The Call Stack is a simple data structure provided by the V8 JavaScript engine.
The job of the call stack is to track the execution of our program and it does that by keeping track
of all of the functions that are currently running.
Now you've actually seen a call stack before.
If you remember in the last section we did bugged an error message that we intentionally created in
our program and we saw two things.
We saw the actual error message and below that we saw a long list of all of the functions that were
running to get to that point in the program.
That is a call stack.
Now the data structure for the call stack could not be simpler.
You can add something onto the top of the list and you can remove the top item.
That is it.
So think of it like a can of tennis balls.
Not that I've ever played tennis.
You can add a tennis ball onto the top by dropping it into the can and if you want to remove one you
have to remove the top one.
I couldn't remove one in the middle without first removing the ones above it and I couldn't add something
to the bottom of the list if there were already things inside.
So let's go ahead and see how the call stack is going to help us execute our simple program on the left
hand side.
The first thing that's going to happen is that our script.
It's gonna get wrapped in that main function that no J.S. provides in the last section when you debug
do your know J.S. applications using Chrome.
You saw that you had your application code showing up in the Chrome browser but we also saw that our
code was wrapped inside of a function that we did not create.
That function was defined by node.
And while it's an anonymous function it's often referred to as the main function for the program.
So what's the first thing that happens.
The main function gets pushed onto the call stack dropping all the way to the bottom since there's nothing
else inside.
Now when something is added onto the call stack that means it's going to get executed.
So we're gonna kick things off up here with line 1.
We create a constant.
We create a constant X with the value of one.
Then we go ahead and create the constant y the value X plus two which would be one plus two which is
three and then we move on to log the sum is followed by the sum which in this case would be some is
three.
Now log is indeed a function and remember whenever we call a function the function gets added onto the
call stack.
So right here we're going to drop a call to log onto the call stack.
So we have main and we have log.
Now once log is dropped on that's actually going to run and we are going to see our log show up.
So in the so we would get some is three printing and that's exactly what we would see if we ran the
program.
Now when a function finishes by either running to the end or returning a value it gets removed from
the call stack.
Since it's no longer executing.
So at this point the has done its job it printed something to the console.
It's now going to finish by getting removed from the call stack.
Here our little blue era would go on to the next line of the program which is actually the end of the
script which means our main function is going to finish as well that's going to get popped off the call
stack and we are left with an empty call stack at this point.
The program is done now.
This is just the first basic example to get comfortable with how the call stack is going to work.
The next example is still a synchronous example but there's a bit more complexity with multiple function
calls.
If we take a brief look at the script I can see I define a list locations function it takes in an array.
And for each location it loops through it printing it to the console down below I define the locations
and I pass them into the function let's see exactly how things would run should we run this script.
So once again the first thing that happens is the main function gets pushed on to the call stack that
allows the script to start executing right here on line 1.
We define it the list locations variable creating the function which is the variables value.
Now at this point we are not calling the function.
So it's not going to appear on the call stack.
The next thing that happens is we move on to line 7 and this is where we define our my locations array
adding a couple of locations in from there we move on to line nine and that's where we call list locations
with the array of locations.
Now this is indeed a function call.
So we're going to see list locations added on to the call stack.
It's gonna get pushed onto the stack.
Now it's the top item and I've just summarized the argument value so it all fits in this nice purple
block.
So from their list locations is actually going to start running.
That's the function that's defined here and ends down below.
Now the only thing inside of this function is a call to the for each method where looping over each
location provide it.
So for each that is indeed a function call it's also going to get added onto the call stack.
And I have dot dot dot in place of its true argument which is the function to run this function is going
to run one time for each location it gets access to the individual location and it prints it.
So that's the next thing that's going to happen in the program for each is going to be responsible for
calling this function multiple times.
And the first time it gets called it does indeed get added onto the stack.
So right here what happens.
We see that the anonymous function is called with the argument Philly and then from there we actually
call console dialog a another function.
So that gets added onto the stack as well.
Now console dot log once again is indeed going to print something.
So we'll see that appear down below.
Now console dot log is going to finish.
So that's going to get popped off these stack and once console dialogue is finished our little anonymous
function which starts here and ends here that's also going to finish since console dot log was the only
statement inside of there.
So that goes ahead and gets popped off the stack as well.
Now for each doesn't get popped off the stack because it's not quite done yet.
It still has to call the anonymous function again to make sure that New York City prints.
So we are going to see a new anonymous function added on to the call stack and then from there we're
going to see another console dot log call this time printing NYSE that's going to show up down below.
And then from there we will indeed pop off the console log call and the anonymous function call.
Now at this point for each has gone through that process two times there are only two items in the array.
So for each is done.
And that's going to get popped off the call stack as well.
Now that for each has done list of locations is also done as that's the only thing that list locations
does.
It just calls for each win for each has done the functions over.
So right here that gets popped off the stack.
Now that brings us back to where we were before online nine of the main function that is the last line
in the program which means that we are all done.
The final result we have Philly printing and then below we have NYC printing.
So here we were able to get an idea for how the call stack is going to allow us to work through our
program keeping track of the individual functions that are actually executing.
Now let's go ahead and move on to the third and final example.
This is our asynchronous example that we actually wrote out and ran in the last video and we're going
to explore how it ran behind the scenes so we can figure out why we were seeing things in the order
we were seeing.
Now for this one since it is a synchronous we will be using the call stack along with node API is the
callback queue and the event loop all working together to get our application running.
Now like with our other synchronous examples the first thing that happens is that main gets added onto
the V8 call stack that starts the execution of our program.
We start on line one with a call to log.
We've already seen what happens when we do that log it gets added onto the call stack.
Our message shows up over here and then log gets removed as the function completes.
Next up as you might have expected we move on to line 3.
That is a call to set time out set time out is clearly a function.
So something new gets pushed onto the call stack.
Now set time out is not a part of the javascript programming language.
You're not going to find its definition anywhere in the javascript spec and V8 has no implementation
for it.
Instead it is node j s which creates an implementation of set time out using C++ and provides it to
your know J.S. scripts to use as we saw it is an asynchronous way to weight a specific amount of time
and then have a function run.
So when we call set time out it's really registering an event with no J.S. API.
And that is an event callback pair where the event in this case is simply to wait two seconds and the
callback is the function to run another event callback pair might be to wait for a database request
to complete then run the callback that does something with the data.
So right here when we call set time out a new event gets registered in node API is here we have our
set time out callback and we're waiting for two seconds.
Now at this point in the process that 2 second clock starts ticking down.
Well we're waiting for those two seconds to happen.
We can actually do other stuff inside of the call stack so JavaScript itself is a single threaded programming
language.
You can do one thing at a time and the call stack enforces that we can only have one function on the
top of the call stack that is the thing we're doing.
There's no way to execute two things at the same time.
Now that doesn't mean no JSA is completely single threaded the code you run is indeed still single threaded
but node uses other threads in C++ behind the scenes to manage your events.
That's what allows us to continue running our application while we're waiting those two seconds.
We don't have to completely wait and this is the non blocking nature of note this is not blocking the
rest of the app from running.
So from here what do we do we move on to a another set time out call.
We go on to line 7 we call a set time out again.
This is going to register yet another event in the node API EIS area a callback where the event is 0
seconds.
And at that point we now have to node API is waiting in the background so we can still continue to do
other things while both of those are waiting for the event to complete in the first case two seconds
in the second case zero.
Now where do we go from here while these zero seconds are up.
So this callback needs to get executed.
Now how exactly does that happen.
Well this is where the callback queue and the event loop down below come into play.
The job of the callback queue is simple.
Its job is to maintain a list of all of the callback functions that are ready to get executed.
So when a given event is done in this case when the zero second timer is complete that callback function
the function we defined right here that's gonna get added on to the callback Q which is just a standard
line you get in at the end of the line and you work your way towards the front the front item is the
one that will get executed first.
So right here since there are no items in the list the callback gets added right up front.
So we have this callback and it's ready to get executed but before it can be executed it needs to be
added onto the call stack.
That's where functions go to run.
Now this is where the event loop comes into play the event loop looks at two things it looks at the
call stack and it looks at the callback Q If the call stack is empty it's going to run items from the
callback.
Q So at this point the event loop says I know you got added to the callback queue but the call stack
is not empty so I can't execute you.
And this is why our function doesn't run right away.
The event loop needs to wait for the call stack to be empty.
So at this point Maine actually continues to run the next thing we see is that line eleven of our program
is going to run.
That is a call to log.
So the function gets added onto the call stack our message prints.
Down below.
The function gets popped off the call stack and at this point the main function is done.
So from here main gets removed.
Now with our regular synchronous scripts this is when the program actually finished the end of Main
signified the end of the application.
That is not the case with our asynchronous programs right now the event loop can start to do its job.
It can see that the call stack is empty and it can say OK.
Do I have anything in the callback q.
I do so it takes that item and it moves it up to the call stack so the callback can run.
So at this point our callback function is running.
That is going to execute the function.
Right here there is a single line inside of there.
It is a call to luck that gets added onto the call stack.
Our message prints printing 0 seconds it gets removed and then the callback function is done.
So this is why we were seeing zero seconds after finishing up none of our asynchronous callbacks are
ever going to run before the main function is done.
So at this point in the program still isn't done.
The call stack is empty.
The callback Q is empty which means the event loop can't do anything.
The program just sits there for two seconds.
At that point our other event is done.
It's callback gets pushed onto the callback queue the event loop detects that it notices the call stack
is empty which means it's ready to run.
It takes that callback bringing it up to the call stack and it executes it.
So that is defined on line 4.
We have our call to log.
We get our message to print.
Printing 2 seconds that gets removed the callback gets removed and at this point the program is complete
the call stack is empty.
The callback Q is empty and there are no other events registered with nodes API IDs.
This means the process would be complete and over here we have the exact same output we got when we
actually ran the application.
The only difference is that we now know why we got the messages printing in the order we saw them because
node uses other threads behind the scenes for those node API as we could see why node is Nana blocking
allowing finishing up to print.
Even though we're waiting 2 seconds for our other message to print we also learned why we were seeing
finishing up print before 0 seconds.
That's because the event loop can't run any of our asynchronous callbacks until the call stack is empty
which means that main needs to finish first.
If you have any questions about what was covered here just crack open a question in the Q and A.
And remember this is not the end of our discussion on asynchronous programming.
This is just the beginning.
The goal here was to give us a mental model of what's happening now.
We're gonna dive into the rest of the section and actually explore how we can get real data from each
TTP API as into our application.
I'm excited to get to that and so let's go ahead and jump right in to the next video.