WEBVTT

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.

