Jonas: So, now that you're super comfortable
with consuming promises and also building promises,
let's turn our attention back
to actually consuming promises.
That's because since ES 2017,
there is now an even better
and easier way to consume promises,
which is called async/await.
So let me show you how it works.
So we start by creating a special kind of function,
which is an async function.
So in this lecture, we will basically recreate
the whereAmI function that we have been building.
whereAmI,
and so function,
but for now, we will pass in the country again
to make it simple at the beginning.
But as I was saying,
we now need to make this a special kind of function,
which is an async function.
And we do this by simply adding async
here in front of the function.
And so this function is now an asynchronous function.
So a function that will basically keep running
in the background while performing the code
that's inside of it.
Then, when this function is done,
it automatically returns a promise.
But more on that in the next video.
For now, what's important is that inside an async function,
we can have one or more await statements.
So, await,
and then here, we need a promise.
And so we can use the promise
returned from the fetch function.
And so let's now use our API again
to search for a country, basically.
So let's see where we have some information about that.
And here we go.
So this is the URL that we have been using.
So make sure you grab it somewhere from your code.
And so here, let's now pass in this country again.
All right.
So, again, this year, we'll return a promise,
and so in an async function like this one,
we can use the await keyword
to basically await for the result of this promise.
So, basically, await will stop the code execution
at this point of the function
until the promise is fulfilled.
And so, until the data has been fetched, in this case.
But now, after that explanation,
you might think, "Isn't stopping the code,
blocking the execution?"
Well, that's a really good question,
but the answer is actually no, in this case.
Because stopping execution in an async function,
which is what we have here,
is actually not a problem
because this function is running asynchronously
in the background.
And so, therefore,
it is not blocking the main thread of execution.
So, it's not blocking the call stack.
And in fact, that's what's so special about async/await.
So it's the fact that it makes our code
look like regular synchronous code,
while behind the scenes, everything is in fact asynchronous.
All right.
But, anyway, as soon as this promise here is resolved,
then the value of this whole await expression
that we have here is going to be
the resolved value of the promise.
And so we can simply store that into a variable.
So let's call it res for response.
And then, here, we can take a look at that response.
And just to show you that this function here
is actually asynchronous,
let's log something to the console before we call it.
So just first, because this should be printed first, right?
And then, or actually, we should call the function first.
So whereAmI with Portugal.
But even by doing this,
this console.log('FIRST') will be displayed first.
Because, again, this is an async function,
and so once the function is called,
it is then loaded off to the background.
And so this fetch here will be running in the background
without blocking our main thread.
And so the code will move on to the next line,
which is then this console.log('FIRST').
All right.
And so, indeed, we got the FIRST printed first,
and then here we got the response.
But this time, we got this response
in this really nice and elegant way.
So you see here that by using async/await,
our asynchronous code here
really looks and feels like synchronous code.
So we can simply await until the value
of the promise is returned, basically,
and then just assign that value to a variable.
And that is something that was impossible before.
So before we had to mess with callback functions,
and that was true in callback hell,
but also by consuming promises with the then method.
But now with the async/await,
that is just completely gone, right?
So again, this looks now like normal synchronous code,
where we simply assign values to a variable.
And that makes it so much easier
and more clean in my opinion.
Now, before you start using async/await all over the place,
you need to first understand that async/await
is in fact simply syntactic sugar
over the then method in promises.
So, of course, behind the scenes,
we are still using promises,
we are simply using a different way
of consuming them here in this case.
But what we have here, so this,
is essentially exactly the same
as doing it the old way, basically.
So using then and then res,
and then console.log(res), like we did here.
So this is exactly the same.
So let's put that here,
and comment it out, of course.
Because what we are interested in
is indeed async/await right now.
So now that we know how async/await works,
it's time to actually recreate the whereAmI function.
So first off, we need to get the JSON
out of this response, right?
And so, remember, on the response,
we need to call a JSON.
And remember that this itself returns a new promise.
And so previously, we would have to return this promise
and then chain another then handler.
But now, this becomes so much easier.
All we have to do is to, again, await this,
and then we can store the results directly
into the data variable that we have been using before.
All right. And so, here it is.
So here is the same data as before,
and so now all we need to do is to render it.
So render country and data at position zero.
And in case you skipped any of the previous videos
and don't have this render country function for some reason,
you can simply get it from the final files of this section,
from the GitHub repository.
So from where you also got the starter files.
Now okay.
And, yeah, there is our data,
so rendered to the page here.
Great. And all without the chaining of promises
like we had before.
So this is really elegant, one more time,
simply being able to essentially store
the fulfilled promise value immediately into a variable
without having to mess with callback functions.
Now, okay. But now,
let's actually finish the function here
with all the other functionality as well.
So with geolocation and also reverse geocoding.
So for that, we need to get our promise
that we built before for geolocation.
So, this is the one here, so let's get it.
And so, again, async/await is only about consuming promises.
The way that we built them is not influenced in any way.
All right.
So this year is going to work the exact same way.
And so let's do that here before.
And so getPosition, remember,
it doesn't need any arguments.
And so, as you know, all we have to do is to now await this
and then store the result into a variable.
And just like before, let's simply destructure this.
And in fact, let me get the code from before
so we don't have to repeat everything.
So that was this code.
And we also need the reverse geocoding, right?
So, let's paste all of that here.
So, what we want here is to get the latitude
and longitude from pos.coords.
So probably, we should just call this here,
first, the position.
And then from pos.coords,
we get the lat and longitude, just like before.
And then, now, the next one.
So now we can use these latitude and longitude
and one more time plug them into this reverse geocoding API.
And so now, again, it becomes a lot easier
to basically chain promises,
because we don't have to return anything,
we don't have to create new then methods
and we don't have to create new callback functions.
So all we have to do is to await this
and store the result into some variable.
So res for response.
But we already have that,
so let's call it geo for geocoding.
And so let's take a look at that,
or actually, not yet,
because remember that this is going to be just a response,
and so we need to get the JSON from there.
And yet another promise.
But this is now so easy and so beautiful to handle.
So again, dataGeo.
Let's give it a save just to format it a little bit.
And I will add some comments here.
So geolocation.
Then reverse geocoding.
And then, country data.
So just to make sure that it worked,
let's take a look at dataGeo.
And, yes,
this is it, right?
And so again, here at the country property, we got Portugal.
And so now we can plug that into this URL.
So that's going to be dataGeo.country.
And so now we can eliminate the country from here.
And we also don't need to pass it in anymore.
And so, let's reload.
And we still get the same data about Portugal
because that is simply where I am right now located.
But in case you're somewhere else,
then you will now get the data about your own country.
So let's just take a minute
and appreciate how beautiful this data flow here is.
Let me just put this comment out here
so we don't clutter our async function, okay?
And so we now have all of this in one nice async function
that runs behind the scenes
until everything here is finished.
So, we are awaiting here 1, 2, 3, 4, 5 promises
in a very easy way in code that now actually looks
and feels like normal synchronous code.
So, to me, personally,
this async/await feature was really
a huge, huge addition to the JavaScript language.
Now, again, just keep in mind
that async/await is just syntactic sugar
over consuming promises.
So it's a bit like classes in JavaScript,
which also hides the true nature
of how things work behind the scenes.
But I think that's no problem,
at least if you already know exactly
how promises and asynchronous JavaScript
actually do work behind the scenes.
And we spent a lot of time in this section
learning all that, and so I'm sure that you will be fine.
Also, async/await is actually used a lot
together with the more traditional then method
of consuming promises, as we will see in the next video.
Now, let me just show you something,
which is when we reload too fast here,
then we should get that same error as before
from the reverse geocoding,
where we can only do three requests per second
or something like that.
Well, I guess I'm not fast enough here.
Oh, okay, but here we go.
So here we have that 403 error.
And so, with this error,
our whole example here falls apart.
So we get this cascade of errors here
and nothing works anymore.
And the reason for all of these errors here
is because right now we actually don't have
any error handling here.
And so let's fix that in the next video.