Let's now shortly go back
to asynchronous JavaScript,
because there has been an important change in ES2022.
So starting from this new ES2022 version,
we can now use the await keyword
outside of async functions, at least in modules.
So that's why this is here in the module section.
So again, as I just said, because this is really important,
we can now basically use the await keyword
outside of an async function,
which we call top-level await.
Just remember that this only works in modules.
If we were gonna try this in a normal script,
like we have been using before this section,
then top level await would still fail,
so it would not work at all.
But here in our HTML file,
we can still see that we have our type set to module.
So this is what is required
in order to make top-level await actually work.
So to show you top level await,
let's simply do a simple fetch request.
So the fetch function, remember,
is what we do to do an HTTP or an AJAX request.
And now let's use a new API that we haven't used before,
which is a very simple one, simply with some fake data.
And it's called JSONPlaceholder.
So just Google json placeholder,
and probably it is then this very first result.
And here, we can get a fake data about posts,
comments, albums, and all of this, but here,
what I'm interested in is these posts.
So just copy this URL here.
And then that's really all that we need.
So let's put that here.
And now it's time to use that top-level await.
So we can await the result here,
and then save it into some variable.
All right, but remember that then we need
another await to parse the data as JSON.
So here I'm not explaining deeply
again how all of this works,
so how the fetch function works and how the JSON works,
because we went through that
in great depth in the previous section.
Okay, and then we can log the data simply to the console.
So let's give it a save and see what happens.
And indeed, here is our data.
So we have an array of 100 posts here
where each of them is this object here.
All right, so basically, that's how you use top-level await.
And so we see that indeed, the await keyword is
now working outside of an async function.
So before, we would have to write async function something,
and then the function body.
But now, with top-level await in modules,
that is no longer necessary.
Now, what's really, really important to understand here is
that while this is all great and very useful,
this actually blocks the execution of the entire module now.
And as we learned in the previous section,
that is sometimes not exactly what we want.
So let me actually demonstrate that to you
by logging something else here afterwards.
So just something really.
And I will also make this request here a little bit slower.
So let's come here to the network tab,
and here, then I click on a throttling,
and let's use a slow 3G.
And let's clean this here and reload.
So you'll see that it's now taking up quite some time.
And especially now here, this part,
where it's actually fetching some data.
So let's actually log something here before also,
so start fetching.
So that will make it a little bit easier
to see what's happening.
So let's reload here again.
So now it all takes a lot of time
because the network is really slow.
So you see it starts fetching, and it's doing the work.
And only after that, it is really logging
this something here to the console.
And so in fact, this await keyword here,
which is now outside of an async function,
is blocking the entire execution of this module,
which is something that we had never seen before.
So this really wasn't possible
before we got top-level await in JavaScript.
Now, of course, this can be useful in some situations,
but many times, it can also be harmful,
and especially if it's a really long running task.
So just as we learned in the last section.
And if you don't remember
that very important video from the last section,
then you can just check it out, I think,
it's the first video in that previous section.
But anyway, long story short,
just make sure that you use this new superpower
that you just got with great caution.
All right, now this example here illustrates exactly
how top-level await works, but it's a bit too simple.
It's not really real world enough.
So let's actually get a little bit more real.
So many times, we have the situations
where we do have an async function
that we want to return some data.
So let's actually try that.
And I will just comment out this code here for now.
Okay.
And so let's create a function here called getLastPost.
So this function will basically do this fetch request here,
and will then only return the very last post.
So this is an async function.
It doesn't need any input data.
And then let's just copy these two lines of code here.
And let's again, actually log that data here
so we can take a look at what we receive here.
So for now, let's just call it
so that this code here actually executes.
And to see this, I will now turn off this throttling.
So we no longer need this.
This was just to show you
the blocking effect of top-level await.
Okay, so that's pretty fast now.
And remember that now we want to return
something from this function.
And I simply want to return an object
which contains the title here.
And let's see, also the body.
So let's say return,
and we're gonna return a new object with the title of data,
which has this entire array here,
and then we want to get the last element.
Now, how can we do that?
Well, let's actually use the new ES2022 at method.
And if this is the first time that you're seeing,
or that you're hearing about the at method,
then check out a new video
that I also added to the array section,
so right at the beginning of that.
But anyway,
we can just use data.at, and then minus one,
which will basically get the very last element of an array,
and then .title.
And then the other one is called the body,
but let's just call it text here.
So text is data at minus one .body.
Give it a save, and now, here,
let's try to save that variable
or actually that returned value
into a variable called lastPost.
Okay, now, if you remember the last section,
then you will remember that this is not going to work.
So let me show you what lastPost is actually going to be.
So you see, it is actually a promise.
It is not the object that we were expecting.
And the reason for that is that calling an async function,
which this function here clearly is,
will always return a promise.
It will not return the actual data itself,
because by the time we are running this line of code here,
the data has not yet arrived.
So we still have that pending promise.
And again, if you don't really remember the specifics here,
you can always go back to the last section.
All right, now, the workaround that I showed you before,
so to actually get this data here,
so this object instead of the promise,
was to simply use regular promises.
So we can take this promise here
that is returned and stored in this variable,
and then on that, we can call the then method.
Then in the then method,
we get access to the resolved value,
which we can just call last,
and then let's just log it to the console.
And of course, it's not called lost, but last.
And so after some time, here we get that object,
so with the title and the text.
However, doing this isn't very clean, not very clean.
And so what we can do now is
to use top-level await for this.
So let's call it lastPost2 this time,
which will be the result of awaiting getLastPost.
And let's see.
Of course it takes some time, but then here it is.
So here is the result of awaiting this promise here now.
So the promise returned from this getLastPost function.
And it's in situations like this
where top-level await actually can get quite useful.
All right.
Now to finish, I just want to show you
one more important implication of using top-level await.
And that is the fact that if one module imports
a module which has a top-level await,
then the importing module will wait
for the imported module to finish the blocking code.
So that sounds a bit complicated,
and it sounds more complicated than it actually is.
So let's just demonstrate this with an example.
So let's come here to our shoppingCart module,
which is a module that we import right here.
So remember from the last lecture
that here we are importing the shoppingCart module.
And so let's now just add some blocking code here.
So maybe just here in the very beginning.
So let's say start fetching users,
because this time, we will actually fetch users.
Let's copy all of this.
And this is really just to have some blocking code,
so we don't even need to store the result anywhere.
And here, instead of posts, we can use users,
but in this case, it doesn't really matter,
because we're actually not even saving
the result anymore or anywhere.
So finish fetching.
All right.
And now, to see this effect again,
we should probably throttle
that request again with a slow 3G.
So going back here.
So the first thing that's going to happen is
that the shopping cart is imported.
And so now, we start immediately the start fetching users.
Then only after the fetch is completed,
we get this second console log here.
So that's this one.
And only after all that,
the code in the importing module,
so in script.js is actually executed.
So let's see that again in action.
And so we will now be able to see
that the code in script.js actually has to wait
for the code in shoppingCart.js to finish.
So this top-level await that we have here is
in fact blocking the execution, not only in this module,
but also in the module that is importing it.
So again, it's very important to remember
that using top-level await,
so await outside of any async function
will block the entire module in a way
that we really couldn't block code execution before.
And so this is not only a really helpful tool,
but also one that we need to use with great care.
But anyway, let's now deactivate this code here
so that it's not going to block
when we start going to the next lectures.
All right.
And so yeah, I think we're finished here.
This is how top-level await works.
And so let's now go straight to the next video.