1
00:00:02,060 --> 00:00:04,630
Now, as a last but very important concept

2
00:00:04,630 --> 00:00:06,170
in this course section,

3
00:00:06,170 --> 00:00:09,150
we'll dive into asynchronous code.

4
00:00:09,150 --> 00:00:12,780
And for that, I'll come back to that readFile example

5
00:00:12,780 --> 00:00:14,580
we had before.

6
00:00:14,580 --> 00:00:16,750
I'll copy the code from errors.js

7
00:00:16,750 --> 00:00:19,750
and add a new async.js file

8
00:00:19,750 --> 00:00:21,910
into which I'll paste that code.

9
00:00:21,910 --> 00:00:25,960
And I'll get rid of the try catch part here

10
00:00:25,960 --> 00:00:28,320
and write it like that instead.

11
00:00:29,470 --> 00:00:33,630
And I will add a data.txt file now actually

12
00:00:33,630 --> 00:00:36,170
where I just say this works,

13
00:00:36,170 --> 00:00:38,820
data from the text file!

14
00:00:38,820 --> 00:00:42,593
So just some basic text that's stored in this text file.

15
00:00:43,680 --> 00:00:47,200
And in async.js, I'll try to read that TXT file

16
00:00:47,200 --> 00:00:48,580
instead of a JSON file.

17
00:00:48,580 --> 00:00:50,393
So I changed that extension.

18
00:00:51,640 --> 00:00:54,280
We also don't need to create a path to that file

19
00:00:54,280 --> 00:00:57,630
since it sits very much next to the code file

20
00:00:57,630 --> 00:00:59,470
where we execute this line of code

21
00:00:59,470 --> 00:01:02,170
and in that case, we can just refer the TXT file

22
00:01:02,170 --> 00:01:04,349
by its name like that.

23
00:01:04,349 --> 00:01:07,033
Now, I'll also get rid of that line here.

24
00:01:08,070 --> 00:01:10,780
And if we now save everything,

25
00:01:10,780 --> 00:01:14,040
and I then execute async.js,

26
00:01:14,040 --> 00:01:15,780
we don't get an error anymore.

27
00:01:15,780 --> 00:01:18,670
Instead, we get this strange buffer thing

28
00:01:18,670 --> 00:01:22,145
but that's just how the file data is actually read in.

29
00:01:22,145 --> 00:01:24,870
This will go away if we, for example,

30
00:01:24,870 --> 00:01:28,790
call toString on FileData to force a conversion

31
00:01:28,790 --> 00:01:30,380
to a human-readable string.

32
00:01:30,380 --> 00:01:34,490
It's a built-in method you can call on basically all objects

33
00:01:34,490 --> 00:01:38,700
and values in JavaScript to force a conversion to a string.

34
00:01:38,700 --> 00:01:41,990
And if I force that with toString here,

35
00:01:41,990 --> 00:01:45,170
and I then execute asynx.js again,

36
00:01:45,170 --> 00:01:47,080
then I see the actual text

37
00:01:47,080 --> 00:01:48,743
that was stored in the file.

38
00:01:50,020 --> 00:01:53,400
Now, of course, that's still nothing new in the end.

39
00:01:53,400 --> 00:01:56,800
Before, we didn't have to do this toString thing

40
00:01:56,800 --> 00:02:00,080
because we used JSON.parse to parse the content

41
00:02:00,080 --> 00:02:01,380
of a JSON file.

42
00:02:01,380 --> 00:02:04,200
Now we have to do it because that's not a JSON file,

43
00:02:04,200 --> 00:02:06,120
and we're not using JSON.parse

44
00:02:06,120 --> 00:02:08,750
but in the end, we're still reading in a file

45
00:02:08,750 --> 00:02:11,173
just as we did it before in the course.

46
00:02:12,530 --> 00:02:17,200
But let's think about that file reading operation here

47
00:02:17,200 --> 00:02:18,920
for a second.

48
00:02:18,920 --> 00:02:21,410
Is there anything about that operation

49
00:02:21,410 --> 00:02:22,943
that could be special?

50
00:02:24,340 --> 00:02:26,890
Well, actually the name of this method

51
00:02:26,890 --> 00:02:29,320
is already a bit strange.

52
00:02:29,320 --> 00:02:31,447
Why is it readFileSync?

53
00:02:33,670 --> 00:02:37,240
Because here we actually force NodeJS

54
00:02:37,240 --> 00:02:39,500
through the file system package

55
00:02:39,500 --> 00:02:43,023
to synchronously process and read that file.

56
00:02:44,660 --> 00:02:48,773
And the opposite of that would be asynchronous processing.

57
00:02:50,990 --> 00:02:52,583
But what's that all about?

58
00:02:53,730 --> 00:02:57,270
Well, the special thing about reading a file

59
00:02:57,270 --> 00:02:59,480
is that this is a process,

60
00:02:59,480 --> 00:03:02,470
which could take quite a while.

61
00:03:02,470 --> 00:03:05,180
We've all been there where we wanted

62
00:03:05,180 --> 00:03:10,160
to open a large PDF or Excel or image file,

63
00:03:10,160 --> 00:03:14,020
and it took a couple of seconds until that file opened

64
00:03:14,020 --> 00:03:15,650
on our system.

65
00:03:15,650 --> 00:03:18,600
Totally outside of NodeJS and coding,

66
00:03:18,600 --> 00:03:21,630
just by double clicking on a file, right?

67
00:03:21,630 --> 00:03:26,610
We all experienced that opening files can take a while.

68
00:03:26,610 --> 00:03:30,200
The bigger a file is, the longer it takes.

69
00:03:30,200 --> 00:03:33,290
And NodeJS code is no exception.

70
00:03:33,290 --> 00:03:35,940
If you open a file programmatically

71
00:03:35,940 --> 00:03:39,550
to read its content and use it in your program,

72
00:03:39,550 --> 00:03:41,710
that can take a while.

73
00:03:41,710 --> 00:03:45,150
Of course, data.txt is a simple, small file,

74
00:03:45,150 --> 00:03:47,260
which will be opened quickly.

75
00:03:47,260 --> 00:03:48,840
But in web development,

76
00:03:48,840 --> 00:03:50,740
and development in general,

77
00:03:50,740 --> 00:03:52,370
it's also quite common

78
00:03:52,370 --> 00:03:55,860
that you work with bigger files with more content.

79
00:03:55,860 --> 00:03:57,890
Now, if you open such a large file

80
00:03:57,890 --> 00:04:02,890
with readFileSync, what happens is that code execution

81
00:04:03,170 --> 00:04:07,790
will be blocked until that file was read in

82
00:04:07,790 --> 00:04:10,630
and parsed by NodeJS.

83
00:04:10,630 --> 00:04:12,470
That means the lines thereafter

84
00:04:12,470 --> 00:04:16,980
will not execute before this line is done.

85
00:04:16,980 --> 00:04:19,420
Now, here that's actually helpful

86
00:04:19,420 --> 00:04:21,779
because outputting the file content

87
00:04:21,779 --> 00:04:24,890
only makes sense after the file was read.

88
00:04:24,890 --> 00:04:27,656
So we wanna wait for this to finish.

89
00:04:27,656 --> 00:04:31,003
But you might have other operations

90
00:04:31,003 --> 00:04:34,030
that you might wanna start at the same time

91
00:04:34,030 --> 00:04:36,640
as you do read that file.

92
00:04:36,640 --> 00:04:39,650
Again, let's say outputting hi there

93
00:04:39,650 --> 00:04:43,060
is something with which we don't want to wait.

94
00:04:43,060 --> 00:04:45,370
Now, of course, we could just put that code

95
00:04:45,370 --> 00:04:47,950
in front of reading the file synchronously

96
00:04:47,950 --> 00:04:52,180
but what if that is also a long-taking operation?

97
00:04:52,180 --> 00:04:54,570
A console.log clearly isn't

98
00:04:54,570 --> 00:04:59,400
but what if we would be reading a database value here?

99
00:04:59,400 --> 00:05:01,560
That could also take quite a while

100
00:05:01,560 --> 00:05:03,650
because we have to establish the connection

101
00:05:03,650 --> 00:05:06,920
to the database, send a request to the database,

102
00:05:06,920 --> 00:05:10,190
query the data and use the data.

103
00:05:10,190 --> 00:05:11,023
So what I'm saying

104
00:05:11,023 --> 00:05:14,350
is that we could have multiple long-taking operations

105
00:05:14,350 --> 00:05:18,513
that are started in the same part of your program.

106
00:05:19,680 --> 00:05:21,340
So therefore, it would be nice

107
00:05:21,340 --> 00:05:24,070
if we could output hi there

108
00:05:24,070 --> 00:05:28,010
and execute line nine before the lines six and eight,

109
00:05:28,010 --> 00:05:30,901
which depend on each other are finished.

110
00:05:30,901 --> 00:05:34,210
And that's where asynchronous code execution

111
00:05:34,210 --> 00:05:36,160
comes into play.

112
00:05:36,160 --> 00:05:37,750
For reading a file,

113
00:05:37,750 --> 00:05:40,890
we actually have this synchronous version

114
00:05:40,890 --> 00:05:43,760
but we also have the asynchronous version

115
00:05:43,760 --> 00:05:45,913
without sync in the name.

116
00:05:47,130 --> 00:05:50,053
Now the code will execute a bit differently.

117
00:05:51,010 --> 00:05:53,390
If we save it like that,

118
00:05:53,390 --> 00:05:58,390
and we then execute async.js, we get an error.

119
00:06:00,290 --> 00:06:04,890
Now I get a invalid callback error here.

120
00:06:04,890 --> 00:06:06,075
And what's that?

121
00:06:06,075 --> 00:06:11,075
Well, readFile now actually requires a second argument,

122
00:06:11,740 --> 00:06:13,591
a second parameter value

123
00:06:13,591 --> 00:06:16,650
that should actually be a function.

124
00:06:16,650 --> 00:06:19,880
Either a function which you defined in advance,

125
00:06:19,880 --> 00:06:22,580
which name you now use

126
00:06:22,580 --> 00:06:24,870
or an anonymous function,

127
00:06:24,870 --> 00:06:27,240
which you define just in time

128
00:06:27,240 --> 00:06:28,570
as we did it before

129
00:06:28,570 --> 00:06:31,853
when we worked with Express and its route handlers.

130
00:06:33,360 --> 00:06:35,900
This is a function, this function here,

131
00:06:35,900 --> 00:06:39,630
that will be executed by readFile

132
00:06:39,630 --> 00:06:42,143
once processing that file is done.

133
00:06:43,040 --> 00:06:45,650
So it's a little bit like adding an event listener

134
00:06:45,650 --> 00:06:47,700
and waiting for clicks.

135
00:06:47,700 --> 00:06:51,380
What we did in the browser earlier in the course.

136
00:06:51,380 --> 00:06:53,340
There we also defined a function

137
00:06:53,340 --> 00:06:55,840
that should be executed once a click occurs.

138
00:06:55,840 --> 00:06:57,900
Now we're defining a function,

139
00:06:57,900 --> 00:07:00,130
in this case, an anonymous function

140
00:07:00,130 --> 00:07:03,563
that should be executed once parsing that file finished.

141
00:07:05,450 --> 00:07:06,283
Now, for the moment,

142
00:07:06,283 --> 00:07:10,190
I'll just console.log file parsing done here,

143
00:07:10,190 --> 00:07:12,023
and then again save everything.

144
00:07:14,193 --> 00:07:18,190
If we now execute this program again,

145
00:07:18,190 --> 00:07:20,070
I get another error.

146
00:07:20,070 --> 00:07:23,453
Cannot read property toString of undefined.

147
00:07:24,830 --> 00:07:27,860
Now, this error is now coming from line 10,

148
00:07:27,860 --> 00:07:29,633
as it also tells you here.

149
00:07:30,650 --> 00:07:33,560
It tells you here that it's line 10

150
00:07:33,560 --> 00:07:35,970
and it even shows you the code line

151
00:07:35,970 --> 00:07:39,433
and the place in code that's causing that issue.

152
00:07:40,390 --> 00:07:42,370
It's this line of code

153
00:07:42,370 --> 00:07:43,860
and specifically the fact

154
00:07:43,860 --> 00:07:47,093
that we're executing toString on fileData.

155
00:07:49,621 --> 00:07:52,670
The problem is that fileData now all

156
00:07:52,670 --> 00:07:54,930
of a sudden is undefined.

157
00:07:54,930 --> 00:07:57,480
That's what it's telling us here.

158
00:07:57,480 --> 00:08:01,430
And you learned that undefined is a built-in value type,

159
00:08:01,430 --> 00:08:05,000
which is basically used if no value exists

160
00:08:05,000 --> 00:08:06,943
in a variable or constant.

161
00:08:08,170 --> 00:08:11,160
Now, why is fileData now undefined

162
00:08:11,160 --> 00:08:13,913
when we did actually parse that file?

163
00:08:15,070 --> 00:08:16,640
Because as I explained,

164
00:08:16,640 --> 00:08:21,180
readFile now starts this file parsing and reading

165
00:08:21,180 --> 00:08:23,700
in a asynchronous way,

166
00:08:23,700 --> 00:08:28,130
which simply means it tells NodeJS to start reading the file

167
00:08:28,130 --> 00:08:30,770
and then it immediately continues

168
00:08:30,770 --> 00:08:32,500
with the next line of code.

169
00:08:32,500 --> 00:08:34,063
In this case, line 10.

170
00:08:35,220 --> 00:08:39,049
It does not wait until reading that file is done.

171
00:08:39,049 --> 00:08:40,980
And even though reading that file

172
00:08:40,980 --> 00:08:43,159
will be super quick in this case,

173
00:08:43,159 --> 00:08:44,840
since it's a small file,

174
00:08:44,840 --> 00:08:47,460
it will still take one or two milliseconds

175
00:08:47,460 --> 00:08:48,783
or something like that.

176
00:08:49,850 --> 00:08:52,340
And therefore, executing this line of code,

177
00:08:52,340 --> 00:08:55,030
line 10, will definitely be quicker

178
00:08:55,030 --> 00:08:56,600
than this file parsing,

179
00:08:56,600 --> 00:08:58,750
even if it is just one millisecond

180
00:08:58,750 --> 00:09:01,810
but the execution of the next line is pretty much instant.

181
00:09:01,810 --> 00:09:04,283
Faster than one millisecond.

182
00:09:05,610 --> 00:09:09,190
Therefore, in line 10, fileData is undefined

183
00:09:09,190 --> 00:09:12,370
because we're not done with reading the file.

184
00:09:12,370 --> 00:09:15,370
And indeed, readFile, when executed like this

185
00:09:15,370 --> 00:09:18,690
in the asynchronous version works totally different

186
00:09:18,690 --> 00:09:21,031
than readFileSync.

187
00:09:21,031 --> 00:09:23,450
It does not return the fileData,

188
00:09:23,450 --> 00:09:25,931
so we can't store the fileData here

189
00:09:25,931 --> 00:09:28,803
in a fileData variable or constant.

190
00:09:29,680 --> 00:09:34,680
Instead, the parsed fileData will only be made available

191
00:09:34,810 --> 00:09:38,900
in this function, a so-called callback function

192
00:09:38,900 --> 00:09:42,030
since it will be called by readFile for us

193
00:09:42,030 --> 00:09:45,080
once it's done with its operation.

194
00:09:45,080 --> 00:09:48,950
Hence, this function here will actually receive values,

195
00:09:48,950 --> 00:09:52,293
parameters passed in automatically by readFile.

196
00:09:53,610 --> 00:09:56,810
To be precise, it will receive an error object,

197
00:09:56,810 --> 00:10:00,380
which will be undefined if no error occurred

198
00:10:00,380 --> 00:10:02,670
but which will hold error information

199
00:10:02,670 --> 00:10:05,280
if reading the file failed.

200
00:10:05,280 --> 00:10:07,360
And it will hold the fileData

201
00:10:07,360 --> 00:10:11,003
if parsing and reading the file did succeed eventually.

202
00:10:12,060 --> 00:10:14,480
Hence, if we then wanna work with that file,

203
00:10:14,480 --> 00:10:17,590
we have to do that from inside this function,

204
00:10:17,590 --> 00:10:22,590
which we pass as a second parameter value to readFile

205
00:10:22,630 --> 00:10:25,380
because only inside of that function,

206
00:10:25,380 --> 00:10:28,560
the fileData will be available.

207
00:10:28,560 --> 00:10:32,480
Not in the code after this code block

208
00:10:32,480 --> 00:10:36,580
because this now starts this asynchronous operation

209
00:10:36,580 --> 00:10:40,110
and the code lines after this asynchronous operation

210
00:10:40,110 --> 00:10:44,873
are executed before that asynchronous operation finished.

211
00:10:45,710 --> 00:10:50,400
And that would allow us to execute and start multiple,

212
00:10:50,400 --> 00:10:53,840
potentially long-taking asynchronous tasks

213
00:10:53,840 --> 00:10:57,723
at the same time without blocking script execution.

214
00:10:59,480 --> 00:11:01,870
So therefore, now with that adjustment made,

215
00:11:01,870 --> 00:11:05,020
if I now execute async.js again,

216
00:11:05,020 --> 00:11:08,250
you see, we first of all see hi there!

217
00:11:08,250 --> 00:11:09,990
That's our first output there

218
00:11:09,990 --> 00:11:13,298
even though it's the last line of code in this function

219
00:11:13,298 --> 00:11:15,920
but it's the first output we get here

220
00:11:15,920 --> 00:11:20,060
because as I said, code execution does directly move on

221
00:11:20,060 --> 00:11:23,940
to line 11 after reading the file was started,

222
00:11:23,940 --> 00:11:28,100
and it does not wait for the file reading to finish.

223
00:11:28,100 --> 00:11:31,690
That's why the output from inside this callback function,

224
00:11:31,690 --> 00:11:35,690
which is only executed once file reading finished appears

225
00:11:35,690 --> 00:11:37,860
after hi there

226
00:11:37,860 --> 00:11:41,645
because it was executed asynchronously.

227
00:11:41,645 --> 00:11:45,100
And it's hopefully clear what the idea here is

228
00:11:45,100 --> 00:11:48,960
and how that asynchronous code execution works.

229
00:11:48,960 --> 00:11:53,330
And the benefit is simply that you can start one

230
00:11:53,330 --> 00:11:55,850
or multiple long-taking operations

231
00:11:55,850 --> 00:11:59,080
without blocking other code execution,

232
00:11:59,080 --> 00:12:01,870
which can speed up your programs by a lot

233
00:12:01,870 --> 00:12:04,683
if you have multiple long-taking operations.

234
00:12:04,683 --> 00:12:07,880
Therefore, it is considered a best practice

235
00:12:07,880 --> 00:12:12,083
to use async functions like this for such tasks.

236
00:12:13,290 --> 00:12:16,190
Now, how do you know which tasks are long-taking

237
00:12:16,190 --> 00:12:18,070
and which tasks aren't?

238
00:12:18,070 --> 00:12:21,100
Well, commonsense already gets you pretty far,

239
00:12:21,100 --> 00:12:23,520
reading a file, talking to a database,

240
00:12:23,520 --> 00:12:25,620
sending some HTTP request,

241
00:12:25,620 --> 00:12:28,210
these are long-taking tasks.

242
00:12:28,210 --> 00:12:31,130
And we'll see examples, plenty of examples

243
00:12:31,130 --> 00:12:32,284
throughout this course.

244
00:12:32,284 --> 00:12:36,600
And in addition, you can always look up the documentation

245
00:12:36,600 --> 00:12:39,680
of some method from a third-party package

246
00:12:39,680 --> 00:12:42,963
or a built-in package to see how it works.

247
00:12:43,960 --> 00:12:46,700
And if you look up the readFile documentation

248
00:12:46,700 --> 00:12:48,880
in the NodeJS documentation,

249
00:12:48,880 --> 00:12:52,400
then you'll learn that this takes a couple of parameters,

250
00:12:52,400 --> 00:12:55,840
and whenever you see a callback parameter,

251
00:12:55,840 --> 00:12:58,240
then this is a synchronous task

252
00:12:58,240 --> 00:13:00,980
because it wants you to specify a function

253
00:13:00,980 --> 00:13:04,510
that should be executed at some point in the future

254
00:13:04,510 --> 00:13:06,740
once the operation finished.

255
00:13:06,740 --> 00:13:08,900
Here in this case, it even tells us

256
00:13:08,900 --> 00:13:12,300
that it asynchronously reads the entire contents

257
00:13:12,300 --> 00:13:13,180
of a file.

258
00:13:13,180 --> 00:13:17,110
So here in this case, we even get an explicit confirmation

259
00:13:17,110 --> 00:13:19,863
that this is an asynchronous task.

