-: After checking out an example of Asynchronous JavaScript,
let's now dive in a bit deeper
and learn everything you need to know
about Synchronous and Asynchronous JavaScript code,
as well as the Event Loop.
All the code we've been writing in this course
up until this point has always been Synchronous code.
Which simply means that one statement
is processed after the other, line by line,
in a single thread in the JavaScript engine.
Something like this is an example of Synchronous JavaScript,
where the first function is executed,
logs "Hey 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.
This here is an example from our previous lecture.
And as we learned,
this one involves some Asynchronous JavaScript.
Again the first function gets called,
logs "Hey 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 2 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 "Hey There!" is logged to the console.
Now, why does the code move on,
instead of waiting for the timer to finish?
Well, before I show you how and why
this actually works behind the scenes,
let me quickly show 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.
We already talked about the Execution Stack
and also about the Message Queue,
when we first talked about events.
So this should be nothing new to you at this point.
What is new here is the 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 lecture
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.
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 them
because they are also in a JavaScript runtime.
This is exactly where the timer
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 until
it finishes its work all in an Asynchronous way.
Again, the callback function is not called right now,
but instead it stays attached to the timer
until it finishes.
And since the timer keeps working,
basically in the background, we don't have to wait,
and can keep executing our code.
So let's do that.
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 so
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 passed
and the timer disappears.
But what happens to our callback function now?
Well, it simply moves to the Message Queue,
where it waits to be executed
as soon as the Execution Stack is empty.
This is exactly what happens with DOM events as well.
Remember that?
And that's because it actually works the exact same way.
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 happens,
then the callback function is placed on a Message Queue,
ready to be executed.
Alright, so how are these callback functions
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 executed.
And the event loop takes the callback
and pushes it onto the stack,
where a new Execution Context is created for that function.
And that's it.
That's what the event loop does.
Inside that callback function now,
we simply run the log function,
which logs Async "Hey 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 event,
then the Event Loop would continue pushing them
onto the stack until all of them were processed.
And that's how the event loop works.
It's actually quite straight forward, right?
But still,
if you ask 95% of the JavaScript developers out there,
they will not really be able to explain this stuff.
And you just gained a huge competitive advantage over them.
Now please just note, that the Set Timeout function,
that we used here as an example,
is really more to simulate
a more real-world Asynchronous function,
like doing an AJAX request to fetch some data
from an external API, just like we're gonna do
in one of the next lectures, okay?
I hope this made sense to you,
so that you're now ready to move on,
in order to use this stuff in practice.