Now I cleared the play.js file again because to conclude this quick refresher module, I'll dive into
another core concept and that is how to work with asynchronous code and for that, we first of all have
to understand what asynchronous code is.
Let's say I set a timer with set timeout which is a function built into nodejs,
there we define a function that should execute after a certain timer expired,
here I'll use an arrow function,
you could use a named function, whatever you like.
The second argument is the timer, let's say two seconds,
you express it in milliseconds so two seconds are 2000milliseconds. In there I'll simply log
timer is done,
if I now run this file for two seconds, nothing happens and then we see timer is done.
Now this is asynchronous code because it doesn't finish immediately
and it would even be async code if we had one millisecond there,
so if it's super fast, it does not happen immediately.
In other code snippets like if we have console log hello and console log hi, these two snippets are
synchronous code because they are executed right after each other
and yeah technically of course node will take some time to execute them but there is no delay other than
your hardware
so to say and therefore this is synchronous code, this is async code, asynchronous because it does not
execute or finish immediately,
it takes a little time even if that's super short.
And indeed if I execute this file like this, you see hello
and hi
before you see timer's done even though it's super fast because nodejs and Javascript in general does
not block your code execution until that is done, indeed here it will recognize this so-called callback
function,
so a function that should execute in the future, it should call back later once it is done so once this
timer expired here, it will just recognize that and will then immediately move onto the next line
and it will execute all the synchronous code and then execute your async code once this is done.
Which is why we see hello and hi
first even though in our code, timer is done is printed first. And that is a crucial concept you have to understand
in javascript and especially node and I will come back to that throughout the course because it's
so important. Now when working with that and I'll increase this to 2 seconds again to make it even clearer,
then you will see again our sync code runs and then after two seconds, this code runs.
When working with async code, we get multiple techniques of well handling it.
The callback function is one,
the oldest one and you'll see it quite a bit especially in nodejs.
There is nothing wrong with it but you'll face a problem if you have a couple of depending async operations,
so here we set the timer and now let's say I create another function
which I'll name fetch data
and in there, I will also just set a timer because I don't want to set up some database or something
like that where we fetch data from, we'll do all that throughout the course, of course
no worries.
So here again I have another timer in there which takes like one and a half seconds
and now here in fetch data, I need some way of well doing something when this inner timer is done.
So here I will actually expect an argument which I'll name callback because this argument will be a
function I will eventually call in my inner function here once I'm done with the timer and there I can
pass done as a value.
Now in the place where I use fetch data, let's say that's inside of this set timeout call, I call fetch
data like this,
there I now need to pass another callback
and here I will get the text passed by the callback in my function when I execute it,
so we'll get some text here and here I can console log that text.
Now this might look confusing, in the end here I'm creating my own function which gets a callback so
that I can define a function which should execute once this inner timer is done from some other place,
so from this place here, this is the function which effectively is passed in as the callback and I'm executing
that function here.
Now if I save that and I run that, takes 2 seconds then the timer is done
and then after one and a half seconds, I see done.
Now if we have a couple of nested async calls as we have here, we go deeper and deeper from a callback
perspective
and that is why we also have a feature called promises which we can use in nodejs. Now often we'll use
third party packages that already use promises for us,
so the syntax I'll show you now is one you rarely have to write on your own,
that will be done by the packages behind the scenes,
still nice to know. You create a promise inside of our fetch data function here let's say by storing
it in a constant or variable and then by using the new keyword which you use in javascript to create
a new object based on a constructor.
If constructor functions are something that tells you nothing,
check out some basic introduction resource to javascript because constructor functions are a core feature
in Javascript
and here you use the promise constructor function which is built into javascript and nodejs and
this actually also takes a callback which gets two arguments, resolve and reject,
you could name them however you want but these are two functions and the first one completes the promise
successfully,
it resolves it successfully,
the second one rejects it which is like throwing an error.
You then take your async code and move that into there
and again you rarely have to write this on your own,
most packages already do that for you and give you the finished promise which does all the magic behind
the scenes
hidden away from you,
here we do it manually.
So now in that callback we have our own function, set
timeout does not give us a promise API unfortunately, so here we also have to use a callback
but in there, we now no longer use any callback function we get, I get no argument here in fetch
data anymore
instead here, I resolve done let's say,
so I successfully return the resolve value.
Now in fetch data after defining the promise, we just have to return it
and please note this is synchronous code
so actually this will be returned immediately after the promise gets created before the code in the
promises run which will happen sometime later when we actually call that function and when this timer
then completes.
So we now return that promise here and in the place where we call fetch data, we now no longer pass a
callback but we can now use then which is callable on a promise and we return a promise and this simply
allows you to now define the callback function here which will execute once the promise is resolved.
Now what is the advantage of that?
If we had multiple such promises, so let's say I called fetch data again in there,
then I don't have to use then like this and therefore I would end up with nested callbacks again
but instead inside of a promise and then block is part of a promise,
I can just return a new promise and then add the next then block after the previous one, like this.
So now we have a chain of
then blocks, this one gets called on the first promise, then in the then block, I return another promise
and even if that would not give us a promise, instead of a then block returning it would convert it to
a promise that instantly resolves and then we add another
then block which is now referring to this promise here and this is more readable than having infinitely
nested callbacks.
So now if I run that and we see hello hi, the timer is done, we see done and we see done again because
I'm calling fetch data twice.
So this might be difficult to wrap your head around for the first time,
we will reuse it throughout this course and then it will become clearer,
again this code is mostly not written by you but it is a crucial concept that makes our async code more
manageable.
There also is another way of managing this, async await, two special keywords you can use in modern javascript
and I'll have a separate section about this towards
the end of the course. I don't want to introduce it here because it can actually be more confusing than this syntax
here and I'll want to stick to this one to not introduce too many new features at the same time
here.
Async code is something you have to understand though
and if it's not totally clear by now, that is fine though, you will see it throughout the course
a bunch
because we have a lot of asynchronous events in nodejs and I will explain this multiple times,
I'll also explain promises again,
I just want to ensure that you have seen this by now and that you then have a chance of understanding
this, how it works and how we deal with it.