1
00:00:01,230 --> 00:00:02,940
<v Jonas>Let's now shortly go back</v>

2
00:00:02,940 --> 00:00:05,220
to asynchronous JavaScript,

3
00:00:05,220 --> 00:00:10,160
because there has been an important change in ES2022.

4
00:00:10,160 --> 00:00:14,290
So starting from this new ES2022 version,

5
00:00:14,290 --> 00:00:16,920
we can now use the await keyword

6
00:00:16,920 --> 00:00:21,610
outside of async functions, at least in modules.

7
00:00:21,610 --> 00:00:24,793
So that's why this is here in the module section.

8
00:00:26,420 --> 00:00:31,000
So again, as I just said, because this is really important,

9
00:00:31,000 --> 00:00:33,990
we can now basically use the await keyword

10
00:00:33,990 --> 00:00:36,760
outside of an async function,

11
00:00:36,760 --> 00:00:39,800
which we call top-level await.

12
00:00:39,800 --> 00:00:42,900
Just remember that this only works in modules.

13
00:00:42,900 --> 00:00:46,150
If we were gonna try this in a normal script,

14
00:00:46,150 --> 00:00:49,000
like we have been using before this section,

15
00:00:49,000 --> 00:00:52,290
then top level await would still fail,

16
00:00:52,290 --> 00:00:54,260
so it would not work at all.

17
00:00:54,260 --> 00:00:56,270
But here in our HTML file,

18
00:00:56,270 --> 00:01:00,840
we can still see that we have our type set to module.

19
00:01:00,840 --> 00:01:03,340
So this is what is required

20
00:01:03,340 --> 00:01:06,393
in order to make top-level await actually work.

21
00:01:07,700 --> 00:01:09,893
So to show you top level await,

22
00:01:10,750 --> 00:01:13,723
let's simply do a simple fetch request.

23
00:01:16,230 --> 00:01:18,400
So the fetch function, remember,

24
00:01:18,400 --> 00:01:23,290
is what we do to do an HTTP or an AJAX request.

25
00:01:23,290 --> 00:01:27,800
And now let's use a new API that we haven't used before,

26
00:01:27,800 --> 00:01:32,513
which is a very simple one, simply with some fake data.

27
00:01:34,180 --> 00:01:36,223
And it's called JSONPlaceholder.

28
00:01:37,200 --> 00:01:39,520
So just Google json placeholder,

29
00:01:39,520 --> 00:01:43,750
and probably it is then this very first result.

30
00:01:43,750 --> 00:01:46,800
And here, we can get a fake data about posts,

31
00:01:46,800 --> 00:01:50,510
comments, albums, and all of this, but here,

32
00:01:50,510 --> 00:01:53,563
what I'm interested in is these posts.

33
00:01:54,420 --> 00:01:56,823
So just copy this URL here.

34
00:01:57,860 --> 00:01:59,973
And then that's really all that we need.

35
00:02:02,380 --> 00:02:04,350
So let's put that here.

36
00:02:04,350 --> 00:02:07,543
And now it's time to use that top-level await.

37
00:02:09,250 --> 00:02:11,740
So we can await the result here,

38
00:02:11,740 --> 00:02:16,683
and then save it into some variable.

39
00:02:18,350 --> 00:02:20,950
All right, but remember that then we need

40
00:02:20,950 --> 00:02:25,550
another await to parse the data as JSON.

41
00:02:26,480 --> 00:02:28,460
So here I'm not explaining deeply

42
00:02:28,460 --> 00:02:30,230
again how all of this works,

43
00:02:30,230 --> 00:02:34,990
so how the fetch function works and how the JSON works,

44
00:02:34,990 --> 00:02:36,870
because we went through that

45
00:02:36,870 --> 00:02:39,283
in great depth in the previous section.

46
00:02:43,620 --> 00:02:47,853
Okay, and then we can log the data simply to the console.

47
00:02:48,780 --> 00:02:52,060
So let's give it a save and see what happens.

48
00:02:52,060 --> 00:02:55,250
And indeed, here is our data.

49
00:02:55,250 --> 00:02:57,890
So we have an array of 100 posts here

50
00:02:57,890 --> 00:03:00,403
where each of them is this object here.

51
00:03:02,720 --> 00:03:06,860
All right, so basically, that's how you use top-level await.

52
00:03:06,860 --> 00:03:10,280
And so we see that indeed, the await keyword is

53
00:03:10,280 --> 00:03:13,920
now working outside of an async function.

54
00:03:13,920 --> 00:03:18,920
So before, we would have to write async function something,

55
00:03:20,740 --> 00:03:22,310
and then the function body.

56
00:03:22,310 --> 00:03:24,900
But now, with top-level await in modules,

57
00:03:24,900 --> 00:03:27,380
that is no longer necessary.

58
00:03:27,380 --> 00:03:30,980
Now, what's really, really important to understand here is

59
00:03:30,980 --> 00:03:34,610
that while this is all great and very useful,

60
00:03:34,610 --> 00:03:39,240
this actually blocks the execution of the entire module now.

61
00:03:39,240 --> 00:03:41,450
And as we learned in the previous section,

62
00:03:41,450 --> 00:03:44,043
that is sometimes not exactly what we want.

63
00:03:44,990 --> 00:03:47,830
So let me actually demonstrate that to you

64
00:03:47,830 --> 00:03:50,363
by logging something else here afterwards.

65
00:03:52,130 --> 00:03:54,410
So just something really.

66
00:03:54,410 --> 00:03:57,693
And I will also make this request here a little bit slower.

67
00:03:58,830 --> 00:04:01,780
So let's come here to the network tab,

68
00:04:01,780 --> 00:04:06,340
and here, then I click on a throttling,

69
00:04:06,340 --> 00:04:08,123
and let's use a slow 3G.

70
00:04:10,159 --> 00:04:12,493
And let's clean this here and reload.

71
00:04:15,990 --> 00:04:19,120
So you'll see that it's now taking up quite some time.

72
00:04:19,120 --> 00:04:20,960
And especially now here, this part,

73
00:04:20,960 --> 00:04:23,373
where it's actually fetching some data.

74
00:04:24,950 --> 00:04:29,150
So let's actually log something here before also,

75
00:04:29,150 --> 00:04:33,340
so start fetching.

76
00:04:33,340 --> 00:04:35,210
So that will make it a little bit easier

77
00:04:35,210 --> 00:04:36,410
to see what's happening.

78
00:04:38,580 --> 00:04:41,080
So let's reload here again.

79
00:04:41,080 --> 00:04:42,990
So now it all takes a lot of time

80
00:04:42,990 --> 00:04:45,640
because the network is really slow.

81
00:04:45,640 --> 00:04:48,470
So you see it starts fetching, and it's doing the work.

82
00:04:48,470 --> 00:04:51,180
And only after that, it is really logging

83
00:04:51,180 --> 00:04:53,890
this something here to the console.

84
00:04:53,890 --> 00:04:56,900
And so in fact, this await keyword here,

85
00:04:56,900 --> 00:04:59,700
which is now outside of an async function,

86
00:04:59,700 --> 00:05:03,040
is blocking the entire execution of this module,

87
00:05:03,040 --> 00:05:05,930
which is something that we had never seen before.

88
00:05:05,930 --> 00:05:07,860
So this really wasn't possible

89
00:05:07,860 --> 00:05:11,053
before we got top-level await in JavaScript.

90
00:05:12,070 --> 00:05:15,380
Now, of course, this can be useful in some situations,

91
00:05:15,380 --> 00:05:17,950
but many times, it can also be harmful,

92
00:05:17,950 --> 00:05:21,750
and especially if it's a really long running task.

93
00:05:21,750 --> 00:05:24,473
So just as we learned in the last section.

94
00:05:25,720 --> 00:05:27,130
And if you don't remember

95
00:05:27,130 --> 00:05:29,970
that very important video from the last section,

96
00:05:29,970 --> 00:05:32,480
then you can just check it out, I think,

97
00:05:32,480 --> 00:05:35,730
it's the first video in that previous section.

98
00:05:35,730 --> 00:05:38,300
But anyway, long story short,

99
00:05:38,300 --> 00:05:41,460
just make sure that you use this new superpower

100
00:05:41,460 --> 00:05:44,250
that you just got with great caution.

101
00:05:44,250 --> 00:05:49,110
All right, now this example here illustrates exactly

102
00:05:49,110 --> 00:05:52,700
how top-level await works, but it's a bit too simple.

103
00:05:52,700 --> 00:05:55,220
It's not really real world enough.

104
00:05:55,220 --> 00:05:58,033
So let's actually get a little bit more real.

105
00:05:58,900 --> 00:06:01,790
So many times, we have the situations

106
00:06:01,790 --> 00:06:04,280
where we do have an async function

107
00:06:04,280 --> 00:06:07,200
that we want to return some data.

108
00:06:07,200 --> 00:06:10,490
So let's actually try that.

109
00:06:10,490 --> 00:06:14,163
And I will just comment out this code here for now.

110
00:06:16,460 --> 00:06:17,430
Okay.

111
00:06:17,430 --> 00:06:21,023
And so let's create a function here called getLastPost.

112
00:06:23,660 --> 00:06:27,600
So this function will basically do this fetch request here,

113
00:06:27,600 --> 00:06:30,433
and will then only return the very last post.

114
00:06:32,230 --> 00:06:35,820
So this is an async function.

115
00:06:35,820 --> 00:06:38,950
It doesn't need any input data.

116
00:06:38,950 --> 00:06:43,273
And then let's just copy these two lines of code here.

117
00:06:47,220 --> 00:06:50,850
And let's again, actually log that data here

118
00:06:50,850 --> 00:06:53,623
so we can take a look at what we receive here.

119
00:06:57,070 --> 00:06:58,980
So for now, let's just call it

120
00:06:58,980 --> 00:07:01,630
so that this code here actually executes.

121
00:07:01,630 --> 00:07:06,630
And to see this, I will now turn off this throttling.

122
00:07:06,720 --> 00:07:09,770
So we no longer need this.

123
00:07:09,770 --> 00:07:10,910
This was just to show you

124
00:07:10,910 --> 00:07:13,503
the blocking effect of top-level await.

125
00:07:14,700 --> 00:07:17,810
Okay, so that's pretty fast now.

126
00:07:17,810 --> 00:07:20,310
And remember that now we want to return

127
00:07:20,310 --> 00:07:22,160
something from this function.

128
00:07:22,160 --> 00:07:24,620
And I simply want to return an object

129
00:07:24,620 --> 00:07:27,110
which contains the title here.

130
00:07:27,110 --> 00:07:30,643
And let's see, also the body.

131
00:07:34,780 --> 00:07:36,920
So let's say return,

132
00:07:36,920 --> 00:07:40,860
and we're gonna return a new object with the title of data,

133
00:07:44,410 --> 00:07:46,370
which has this entire array here,

134
00:07:46,370 --> 00:07:49,330
and then we want to get the last element.

135
00:07:49,330 --> 00:07:51,520
Now, how can we do that?

136
00:07:51,520 --> 00:07:56,520
Well, let's actually use the new ES2022 at method.

137
00:07:56,730 --> 00:07:59,710
And if this is the first time that you're seeing,

138
00:07:59,710 --> 00:08:02,140
or that you're hearing about the at method,

139
00:08:02,140 --> 00:08:03,960
then check out a new video

140
00:08:03,960 --> 00:08:06,850
that I also added to the array section,

141
00:08:06,850 --> 00:08:09,150
so right at the beginning of that.

142
00:08:09,150 --> 00:08:10,230
But anyway,

143
00:08:10,230 --> 00:08:14,170
we can just use data.at, and then minus one,

144
00:08:14,170 --> 00:08:17,823
which will basically get the very last element of an array,

145
00:08:19,270 --> 00:08:20,823
and then .title.

146
00:08:21,740 --> 00:08:24,680
And then the other one is called the body,

147
00:08:24,680 --> 00:08:26,960
but let's just call it text here.

148
00:08:26,960 --> 00:08:31,283
So text is data at minus one .body.

149
00:08:34,840 --> 00:08:37,810
Give it a save, and now, here,

150
00:08:37,810 --> 00:08:40,740
let's try to save that variable

151
00:08:42,140 --> 00:08:44,210
or actually that returned value

152
00:08:44,210 --> 00:08:46,623
into a variable called lastPost.

153
00:08:48,920 --> 00:08:53,140
Okay, now, if you remember the last section,

154
00:08:53,140 --> 00:08:56,453
then you will remember that this is not going to work.

155
00:08:58,190 --> 00:09:01,453
So let me show you what lastPost is actually going to be.

156
00:09:02,890 --> 00:09:05,890
So you see, it is actually a promise.

157
00:09:05,890 --> 00:09:09,290
It is not the object that we were expecting.

158
00:09:09,290 --> 00:09:13,370
And the reason for that is that calling an async function,

159
00:09:13,370 --> 00:09:15,770
which this function here clearly is,

160
00:09:15,770 --> 00:09:17,770
will always return a promise.

161
00:09:17,770 --> 00:09:20,850
It will not return the actual data itself,

162
00:09:20,850 --> 00:09:24,680
because by the time we are running this line of code here,

163
00:09:24,680 --> 00:09:26,690
the data has not yet arrived.

164
00:09:26,690 --> 00:09:29,540
So we still have that pending promise.

165
00:09:29,540 --> 00:09:32,410
And again, if you don't really remember the specifics here,

166
00:09:32,410 --> 00:09:35,540
you can always go back to the last section.

167
00:09:35,540 --> 00:09:40,230
All right, now, the workaround that I showed you before,

168
00:09:40,230 --> 00:09:42,640
so to actually get this data here,

169
00:09:42,640 --> 00:09:45,210
so this object instead of the promise,

170
00:09:45,210 --> 00:09:47,763
was to simply use regular promises.

171
00:09:50,300 --> 00:09:52,720
So we can take this promise here

172
00:09:52,720 --> 00:09:56,400
that is returned and stored in this variable,

173
00:09:56,400 --> 00:09:59,303
and then on that, we can call the then method.

174
00:10:00,210 --> 00:10:01,550
Then in the then method,

175
00:10:01,550 --> 00:10:04,240
we get access to the resolved value,

176
00:10:04,240 --> 00:10:07,000
which we can just call last,

177
00:10:07,000 --> 00:10:10,393
and then let's just log it to the console.

178
00:10:14,550 --> 00:10:19,390
And of course, it's not called lost, but last.

179
00:10:20,620 --> 00:10:23,870
And so after some time, here we get that object,

180
00:10:23,870 --> 00:10:26,860
so with the title and the text.

181
00:10:26,860 --> 00:10:31,860
However, doing this isn't very clean, not very clean.

182
00:10:32,320 --> 00:10:33,870
And so what we can do now is

183
00:10:33,870 --> 00:10:36,123
to use top-level await for this.

184
00:10:38,160 --> 00:10:42,803
So let's call it lastPost2 this time,

185
00:10:43,960 --> 00:10:47,293
which will be the result of awaiting getLastPost.

186
00:10:55,630 --> 00:10:56,673
And let's see.

187
00:10:57,660 --> 00:11:00,390
Of course it takes some time, but then here it is.

188
00:11:00,390 --> 00:11:04,610
So here is the result of awaiting this promise here now.

189
00:11:04,610 --> 00:11:09,040
So the promise returned from this getLastPost function.

190
00:11:09,040 --> 00:11:11,380
And it's in situations like this

191
00:11:11,380 --> 00:11:14,833
where top-level await actually can get quite useful.

192
00:11:15,870 --> 00:11:16,703
All right.

193
00:11:18,720 --> 00:11:21,020
Now to finish, I just want to show you

194
00:11:21,020 --> 00:11:25,280
one more important implication of using top-level await.

195
00:11:25,280 --> 00:11:28,700
And that is the fact that if one module imports

196
00:11:28,700 --> 00:11:31,770
a module which has a top-level await,

197
00:11:31,770 --> 00:11:34,830
then the importing module will wait

198
00:11:34,830 --> 00:11:38,880
for the imported module to finish the blocking code.

199
00:11:38,880 --> 00:11:41,270
So that sounds a bit complicated,

200
00:11:41,270 --> 00:11:44,620
and it sounds more complicated than it actually is.

201
00:11:44,620 --> 00:11:48,640
So let's just demonstrate this with an example.

202
00:11:48,640 --> 00:11:51,900
So let's come here to our shoppingCart module,

203
00:11:51,900 --> 00:11:54,913
which is a module that we import right here.

204
00:11:56,040 --> 00:11:58,000
So remember from the last lecture

205
00:11:58,000 --> 00:12:01,310
that here we are importing the shoppingCart module.

206
00:12:01,310 --> 00:12:04,483
And so let's now just add some blocking code here.

207
00:12:05,550 --> 00:12:09,223
So maybe just here in the very beginning.

208
00:12:17,090 --> 00:12:21,643
So let's say start fetching users,

209
00:12:22,730 --> 00:12:26,123
because this time, we will actually fetch users.

210
00:12:27,580 --> 00:12:29,403
Let's copy all of this.

211
00:12:32,939 --> 00:12:35,340
And this is really just to have some blocking code,

212
00:12:35,340 --> 00:12:39,340
so we don't even need to store the result anywhere.

213
00:12:39,340 --> 00:12:42,800
And here, instead of posts, we can use users,

214
00:12:42,800 --> 00:12:44,680
but in this case, it doesn't really matter,

215
00:12:44,680 --> 00:12:47,050
because we're actually not even saving

216
00:12:47,050 --> 00:12:49,623
the result anymore or anywhere.

217
00:12:51,070 --> 00:12:53,733
So finish fetching.

218
00:12:56,180 --> 00:12:57,610
All right.

219
00:12:57,610 --> 00:12:59,620
And now, to see this effect again,

220
00:12:59,620 --> 00:13:00,800
we should probably throttle

221
00:13:00,800 --> 00:13:03,613
that request again with a slow 3G.

222
00:13:05,510 --> 00:13:07,283
So going back here.

223
00:13:09,650 --> 00:13:11,700
So the first thing that's going to happen is

224
00:13:11,700 --> 00:13:13,803
that the shopping cart is imported.

225
00:13:16,440 --> 00:13:20,120
And so now, we start immediately the start fetching users.

226
00:13:20,120 --> 00:13:22,660
Then only after the fetch is completed,

227
00:13:22,660 --> 00:13:25,483
we get this second console log here.

228
00:13:26,790 --> 00:13:28,290
So that's this one.

229
00:13:28,290 --> 00:13:30,190
And only after all that,

230
00:13:30,190 --> 00:13:32,470
the code in the importing module,

231
00:13:32,470 --> 00:13:36,590
so in script.js is actually executed.

232
00:13:36,590 --> 00:13:38,980
So let's see that again in action.

233
00:13:38,980 --> 00:13:41,000
And so we will now be able to see

234
00:13:41,000 --> 00:13:44,990
that the code in script.js actually has to wait

235
00:13:44,990 --> 00:13:48,960
for the code in shoppingCart.js to finish.

236
00:13:48,960 --> 00:13:52,050
So this top-level await that we have here is

237
00:13:52,050 --> 00:13:56,000
in fact blocking the execution, not only in this module,

238
00:13:56,000 --> 00:13:58,793
but also in the module that is importing it.

239
00:13:59,720 --> 00:14:02,880
So again, it's very important to remember

240
00:14:02,880 --> 00:14:05,150
that using top-level await,

241
00:14:05,150 --> 00:14:08,610
so await outside of any async function

242
00:14:08,610 --> 00:14:11,600
will block the entire module in a way

243
00:14:11,600 --> 00:14:14,690
that we really couldn't block code execution before.

244
00:14:14,690 --> 00:14:17,550
And so this is not only a really helpful tool,

245
00:14:17,550 --> 00:14:21,280
but also one that we need to use with great care.

246
00:14:21,280 --> 00:14:26,000
But anyway, let's now deactivate this code here

247
00:14:26,000 --> 00:14:27,780
so that it's not going to block

248
00:14:29,090 --> 00:14:31,140
when we start going to the next lectures.

249
00:14:33,290 --> 00:14:34,180
All right.

250
00:14:34,180 --> 00:14:37,180
And so yeah, I think we're finished here.

251
00:14:37,180 --> 00:14:39,520
This is how top-level await works.

252
00:14:39,520 --> 00:14:42,383
And so let's now go straight to the next video.

