Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:01,300 --> 00:00:03,370
Let's now take a minute to learn about
2
00:00:03,370 --> 00:00:06,370
the asynchronous nature of Node.js,
3
00:00:06,370 --> 00:00:09,510
which includes absolutely fundamental topics,
4
00:00:09,510 --> 00:00:13,010
like synchronous, asynchronous, blocking,
5
00:00:13,010 --> 00:00:15,140
and non-blocking code.
6
00:00:15,140 --> 00:00:17,810
And all of this will be really important
7
00:00:17,810 --> 00:00:21,090
in order to understand everything that's coming up
8
00:00:21,090 --> 00:00:22,503
throughout this section.
9
00:00:24,240 --> 00:00:27,620
So this piece of code that we wrote in the last lecture,
10
00:00:27,620 --> 00:00:31,830
to read a file and then, save it's content into a variable,
11
00:00:31,830 --> 00:00:34,400
was in a so-called synchronous way,
12
00:00:34,400 --> 00:00:36,840
which simply means that each statement
13
00:00:36,840 --> 00:00:41,330
is basically processed one after another, line by line.
14
00:00:41,330 --> 00:00:42,540
In this example,
15
00:00:42,540 --> 00:00:45,630
first, the file system module is required,
16
00:00:45,630 --> 00:00:47,630
then, the file is read,
17
00:00:47,630 --> 00:00:50,900
and then, we log the result to the console.
18
00:00:50,900 --> 00:00:53,340
So you see that each line of code
19
00:00:53,340 --> 00:00:57,340
basically waits for the result of the previous line.
20
00:00:57,340 --> 00:00:59,440
Now, this can become a problem,
21
00:00:59,440 --> 00:01:01,500
especially with slow operations,
22
00:01:01,500 --> 00:01:04,190
because each line blocks the execution
23
00:01:04,190 --> 00:01:05,710
of the rest of the code.
24
00:01:05,710 --> 00:01:08,120
And so, we say that synchronous code
25
00:01:08,120 --> 00:01:12,290
is also called blocking code because, again,
26
00:01:12,290 --> 00:01:15,080
a certain operation can only be executed
27
00:01:15,080 --> 00:01:17,740
after the one before has finished.
28
00:01:17,740 --> 00:01:20,850
And because of the way Node.js was designed,
29
00:01:20,850 --> 00:01:24,220
this turns into a huge problem, as we'll see in detail
30
00:01:24,220 --> 00:01:26,190
in the next slide.
31
00:01:26,190 --> 00:01:28,500
So the solution to this problem in Node
32
00:01:28,500 --> 00:01:32,160
is to use asynchronous, non-blocking code.
33
00:01:32,160 --> 00:01:35,380
So in asynchronous code, we upload heavy work
34
00:01:35,380 --> 00:01:38,470
to basically be worked on in the background.
35
00:01:38,470 --> 00:01:40,820
And then, once that work is done,
36
00:01:40,820 --> 00:01:43,370
a callback function that we register before
37
00:01:43,370 --> 00:01:45,730
is called to handle the result.
38
00:01:45,730 --> 00:01:47,540
And during all that time,
39
00:01:47,540 --> 00:01:50,380
the rest of the code can still be executing
40
00:01:50,380 --> 00:01:52,910
without being blocked by the heavy task,
41
00:01:52,910 --> 00:01:55,820
which is now running in the background.
42
00:01:55,820 --> 00:01:59,520
So what this means is that we can effectively defer
43
00:01:59,520 --> 00:02:01,620
or reaction into the future
44
00:02:01,620 --> 00:02:04,530
in order to make the code non-blocking
45
00:02:04,530 --> 00:02:07,676
and this is, of course, much better.
46
00:02:07,676 --> 00:02:09,287
Makes sense?
47
00:02:09,287 --> 00:02:12,203
So, in this example, we use the asynchronous
48
00:02:12,203 --> 00:02:16,390
readFile function, which accepts a callback function.
49
00:02:16,390 --> 00:02:19,120
This will start reading the file in the background
50
00:02:19,120 --> 00:02:22,360
and then, immediately move on to the next statement,
51
00:02:22,360 --> 00:02:25,830
printing to the console the string-reading file.
52
00:02:25,830 --> 00:02:30,530
So, again, you see, we are not blocking the execution here.
53
00:02:30,530 --> 00:02:33,860
Then, when the file is finally completely read,
54
00:02:33,860 --> 00:02:35,870
the callback function will be called,
55
00:02:35,870 --> 00:02:38,100
and so, the data that was read
56
00:02:38,100 --> 00:02:40,270
will then be printed to the console.
57
00:02:40,270 --> 00:02:41,890
So that's quite different
58
00:02:41,890 --> 00:02:43,893
from the synchronous version, isn't it?
59
00:02:44,870 --> 00:02:46,710
Now, the question here is,
60
00:02:46,710 --> 00:02:49,490
why does is actually have to be this way?
61
00:02:49,490 --> 00:02:53,940
What's the problem with blocking code execution in Node.js?
62
00:02:53,940 --> 00:02:57,030
Or, in other words, why do we actually use callback
63
00:02:57,030 --> 00:02:59,770
so many times in Node.js?
64
00:02:59,770 --> 00:03:01,523
Well, let's find out.
65
00:03:03,110 --> 00:03:05,930
And in order to understand these questions,
66
00:03:05,930 --> 00:03:08,220
the first thing that we need to understand
67
00:03:08,220 --> 00:03:11,260
is the fact that a Node.js process,
68
00:03:11,260 --> 00:03:13,760
which is where our application is running,
69
00:03:13,760 --> 00:03:16,410
there's only one single thread.
70
00:03:16,410 --> 00:03:19,720
And the thread is just like a set of instructions
71
00:03:19,720 --> 00:03:22,200
that is run in the computer's CPU.
72
00:03:22,200 --> 00:03:25,200
So basically, the thread is where our code
73
00:03:25,200 --> 00:03:29,270
is actually executed in a machine's processor.
74
00:03:29,270 --> 00:03:33,120
So, remember, Node.js is basically single-threaded
75
00:03:33,120 --> 00:03:36,980
and so, for each application, there's only one thread.
76
00:03:36,980 --> 00:03:40,300
That's just the way Node.js was designed.
77
00:03:40,300 --> 00:03:43,050
Now, what that means is that all the users
78
00:03:43,050 --> 00:03:46,960
accessing your application are all using the same thread,
79
00:03:46,960 --> 00:03:50,040
so, basically, accessing the same thread.
80
00:03:50,040 --> 00:03:53,410
And so, whenever they're interacting with the application,
81
00:03:53,410 --> 00:03:55,860
the code that is run for each user
82
00:03:55,860 --> 00:03:59,810
will be executed all in the same thread at the same place
83
00:03:59,810 --> 00:04:02,490
in the computer running the application.
84
00:04:02,490 --> 00:04:04,900
And that is true no matter if you have
85
00:04:04,900 --> 00:04:09,900
five users, like in this diagram, or 5,000 or 5 million.
86
00:04:10,610 --> 00:04:12,080
All right?
87
00:04:12,080 --> 00:04:15,310
Now, what this also means is that when one user
88
00:04:15,310 --> 00:04:17,959
locks the single thread with synchronous code,
89
00:04:17,959 --> 00:04:19,640
like we just saw before,
90
00:04:19,640 --> 00:04:22,280
then all other users will have to wait
91
00:04:22,280 --> 00:04:24,680
for that execution to finish.
92
00:04:24,680 --> 00:04:27,010
And that might not be a huge problem
93
00:04:27,010 --> 00:04:29,800
if you have like five users,
94
00:04:29,800 --> 00:04:33,350
but it definitely will for thousands or even millions
95
00:04:33,350 --> 00:04:35,393
of users at the same time.
96
00:04:36,440 --> 00:04:39,830
So, imagine there's a user accessing your application
97
00:04:39,830 --> 00:04:43,280
and there's a huge synchronous file read in your code
98
00:04:43,280 --> 00:04:46,630
that will take like one second to load.
99
00:04:46,630 --> 00:04:49,920
This will mean, of course, that for that one second,
100
00:04:49,920 --> 00:04:52,370
all other users will have to wait
101
00:04:52,370 --> 00:04:57,370
because the entire execution is blocked for that one second.
102
00:04:57,490 --> 00:05:00,680
So if those other users want to do some simple tasks,
103
00:05:00,680 --> 00:05:02,940
like logging into your application
104
00:05:02,940 --> 00:05:06,900
or just requesting some data, they won't be able to do so.
105
00:05:06,900 --> 00:05:11,150
They will have to wait until the file is finished reading.
106
00:05:11,150 --> 00:05:15,130
Only when that happens they will finally be able to perform
107
00:05:15,130 --> 00:05:18,113
the simpler tasks, one after another.
108
00:05:19,260 --> 00:05:23,290
Now, please note, that this is a very oversimplified version
109
00:05:23,290 --> 00:05:27,010
of what really happens behind the scenes of Node.js,
110
00:05:27,010 --> 00:05:29,880
which is why we will come back to all of this
111
00:05:29,880 --> 00:05:33,760
in the next section and get an even deeper understanding
112
00:05:33,760 --> 00:05:38,090
of how Node.js handles asynchronous code under the hood.
113
00:05:38,090 --> 00:05:39,370
But at this point,
114
00:05:39,370 --> 00:05:42,170
this is enough for you to understand the concept.
115
00:05:42,170 --> 00:05:44,560
It's better to go step-by-step here
116
00:05:44,560 --> 00:05:46,520
and not make it too confusing
117
00:05:46,520 --> 00:05:49,220
right from the beginning, okay?
118
00:05:49,220 --> 00:05:51,660
Anyway, this is how the situation
119
00:05:51,660 --> 00:05:54,620
would play out with synchronous blocking code,
120
00:05:54,620 --> 00:05:58,460
which is obviously a terrible experience for your users.
121
00:05:58,460 --> 00:06:01,180
And so, it's really your job as a developer
122
00:06:01,180 --> 00:06:03,260
to avoid these kinds of situations
123
00:06:03,260 --> 00:06:05,113
by using asynchronous code.
124
00:06:07,150 --> 00:06:10,180
So, for the same situation, we should, of course,
125
00:06:10,180 --> 00:06:12,780
use the asynchronous file read function,
126
00:06:12,780 --> 00:06:15,190
which instead of blocking the single thread,
127
00:06:15,190 --> 00:06:17,700
does the heavy work in the background,
128
00:06:17,700 --> 00:06:20,170
where it basically stays until it's finished
129
00:06:20,170 --> 00:06:22,700
reading the data from the file.
130
00:06:22,700 --> 00:06:25,950
Of course, we then also register a callback function
131
00:06:25,950 --> 00:06:29,490
to be called once the data is available.
132
00:06:29,490 --> 00:06:32,130
And in this scenario, all the other users
133
00:06:32,130 --> 00:06:35,100
can then perform their tasks in a single thread,
134
00:06:35,100 --> 00:06:38,710
one after another, while the file is still being read
135
00:06:38,710 --> 00:06:40,390
in the background.
136
00:06:40,390 --> 00:06:43,870
Now, once the data is read, our callback function will,
137
00:06:43,870 --> 00:06:46,240
of course, get called to be executed
138
00:06:46,240 --> 00:06:51,240
in the main single thread in order to process the read data.
139
00:06:51,380 --> 00:06:52,460
And that's it.
140
00:06:52,460 --> 00:06:54,720
That's an overview of how Node.js
141
00:06:54,720 --> 00:06:58,000
handles asynchronous behavior in order to implement
142
00:06:58,000 --> 00:07:00,850
the non-blocking I/O model that we talked about
143
00:07:00,850 --> 00:07:03,670
in the intro lecture, all right?
144
00:07:03,670 --> 00:07:07,240
And I/O simply stands for input-output,
145
00:07:07,240 --> 00:07:10,810
which is basically stuff like accessing the file system
146
00:07:10,810 --> 00:07:13,500
and handling network requests.
147
00:07:13,500 --> 00:07:16,470
This is actually the whole reason why Node.js
148
00:07:16,470 --> 00:07:18,830
is completely designed around callbacks,
149
00:07:18,830 --> 00:07:21,190
as you will see throughout the course.
150
00:07:21,190 --> 00:07:24,090
In other programming languages, like PHP,
151
00:07:24,090 --> 00:07:27,260
it works very differently because you get, basically,
152
00:07:27,260 --> 00:07:29,640
one new thread for each new user,
153
00:07:29,640 --> 00:07:32,020
which is a completely different paradigm
154
00:07:32,020 --> 00:07:34,600
and really works completely different.
155
00:07:34,600 --> 00:07:37,620
But the creator of Node.js found this model
156
00:07:37,620 --> 00:07:40,660
to be the best solution for building highly performant
157
00:07:40,660 --> 00:07:42,980
and scalable web applications.
158
00:07:42,980 --> 00:07:46,810
Now, just as a final note here, it's important to know that,
159
00:07:46,810 --> 00:07:48,830
when we use callbacks in our code,
160
00:07:48,830 --> 00:07:53,380
that doesn't automatically make it asynchronous, all right?
161
00:07:53,380 --> 00:07:56,520
So, passing functions around into other functions
162
00:07:56,520 --> 00:07:58,780
is quite common in JavaScript,
163
00:07:58,780 --> 00:08:01,830
but of course, again, that doesn't make them
164
00:08:01,830 --> 00:08:05,110
asynchronous automatically, okay?
165
00:08:05,110 --> 00:08:09,150
It only works this way for some functions in the Node API,
166
00:08:09,150 --> 00:08:11,210
such as the readFile function
167
00:08:11,210 --> 00:08:14,823
and many, many more, as people explore in the future.
168
00:08:16,610 --> 00:08:18,500
And now, just to finish,
169
00:08:18,500 --> 00:08:21,200
since we're talking about asynchronous code here,
170
00:08:21,200 --> 00:08:24,630
just one last note about callback functions.
171
00:08:24,630 --> 00:08:27,670
So, this callback model that we just discussed,
172
00:08:27,670 --> 00:08:29,370
where one function is called
173
00:08:29,370 --> 00:08:32,299
once the one before has finished it's work,
174
00:08:32,299 --> 00:08:36,970
can quickly lead to some hard to read and unmanageable code.
175
00:08:36,970 --> 00:08:39,830
Just take this example where the second file read
176
00:08:39,830 --> 00:08:41,870
depends on the first one,
177
00:08:41,870 --> 00:08:44,800
then, the third file read depends on the second one,
178
00:08:44,800 --> 00:08:47,560
and finally, we want to use the final data
179
00:08:47,560 --> 00:08:49,700
to write a file as a result.
180
00:08:49,700 --> 00:08:52,690
That looks quite confusing, right?
181
00:08:52,690 --> 00:08:54,950
I mean, it's gonna work just fine,
182
00:08:54,950 --> 00:08:57,330
but it's just hard to reason about
183
00:08:57,330 --> 00:09:00,110
and that is just with four levels deep.
184
00:09:00,110 --> 00:09:02,980
Imagine you had like 10 or 20 levels,
185
00:09:02,980 --> 00:09:05,850
which is actually not that uncommon.
186
00:09:05,850 --> 00:09:09,440
Anyway, this is what we call the callback hell.
187
00:09:09,440 --> 00:09:11,370
It's such a common problem,
188
00:09:11,370 --> 00:09:13,780
that it already got its own name.
189
00:09:13,780 --> 00:09:16,920
And do you notice this triangular shape here?
190
00:09:16,920 --> 00:09:20,840
That's a very clear sign that you're in callback hell.
191
00:09:20,840 --> 00:09:24,350
Now, how do we actually escape callback hell?
192
00:09:24,350 --> 00:09:27,600
Well, we can use more advanced tools for handling
193
00:09:27,600 --> 00:09:30,730
asynchronous code, like ES6 promises
194
00:09:30,730 --> 00:09:34,150
or even better, ES8 async/await.
195
00:09:34,150 --> 00:09:36,320
Now, the model that we just talked about
196
00:09:36,320 --> 00:09:37,890
will still be the same.
197
00:09:37,890 --> 00:09:39,960
We just have more elegant ways
198
00:09:39,960 --> 00:09:43,370
of dealing with the code itself and writing it.
199
00:09:43,370 --> 00:09:45,830
And there is a whole optional section
200
00:09:45,830 --> 00:09:50,090
of it later in the course on promises and also, async/await,
201
00:09:50,090 --> 00:09:52,590
so in case you're not familiar with them.
202
00:09:52,590 --> 00:09:55,140
But for now, we will keep using callbacks
203
00:09:55,140 --> 00:09:57,900
because that is what Node originally used
204
00:09:57,900 --> 00:10:00,100
and was designed around.
205
00:10:00,100 --> 00:10:02,030
And now, with that being said,
206
00:10:02,030 --> 00:10:05,240
let's move on and use this asynchronous model
207
00:10:05,240 --> 00:10:07,233
in practice for the first time.
16590
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.