Instructor: Welcome back!
In this video, we're gonna read files and write two files
just like before, but instead in an asynchronous way.
Let's add some comments here before.
So, this is the blocking,
synchronous way, and then, we will do an exercise
in an non-blocking, asynchronous way.
So, we're not gonna do the same thing,
we're just gonna invent some other
kind of crazy exercise here.
So, to read a file in an asynchronous way,
it works like this.
Again, we need the FS module, and then read file,
but this time, not read file sync, of course.
And, again, we pass in the name of the file,
or the path to the file actually,
and so again, it is txt,
and the file that I want right now is called start.txt,
so this one.
Oops, sorry for that.
So, this is the file that I want, on the task is read this,
and I'm gonna explain to you why a bit later.
For now, don't worry about the content here.
So, in the read file,
we actually do not have to specify the file encoding, okay.
And so, the next parameter,
the second one will be a callback function,
and that is what we learned in the last lecture.
So, Node JS is all built around callbacks
in order to implement an asynchronous behavior,
and this is how it works.
So, Node will start reading this file here
in the background, and as soon as it is ready,
it will start the callback function that we specify here.
Okay, and it calls this callback function
with two arguments.
The first one is the error,
and the second one is the actual data, okay?
So, this error first callback style is
very typical in Node JS, okay.
So, many, many times, the first parameter
in a callback will be the error, in case there was any,
and the second one will then be the data, itself.
What matters here is
that the error is usually always the first one, okay?
And so just to test it out for now,
let's simply log through console, the data.
And so, let's now actually test that.
But, before we do this,
let us actually still specify the filing coding here, okay?
So, I'm not one hundred percent sure
that it works without this,
so clean this now, run it again, and here we see read this.
So, let's analyze, again, what happened here.
As soon as this function here is run,
it will start reading this file in the background
without blocking the rest of the code execution.
So, let me actually demonstrate this here.
So, a console.log
will read file, and just to have a bit less confusion there,
let me comment out this part here, okay.
And so, what do you think will happen now?
What log are we gonna see first?
And indeed, first we see will read file,
and, only then, we see read this.
So, again, why did that happen?
So, as I mentioned Node JS will start reading the file
in the background here, and will not block the code,
and will then immediately move on to the next line of code.
And, the next line of code, well, it's this log here,
and so that is the first thing
that will be logged here to the terminal.
Only then, when a file is completely read,
this callback function here will run, okay?
And again, this callback function has access to the error
and the data that was read,
and we could really call this here anything that we wanted.
We could call it text as well, it doesn't really matter,
all that matters is that it is the second argument
in this callback function.
Let's actually go back to data
because I like that way better.
And so, only then, this console.log will run with the data,
so with the text that was in the file.
And so, that's why we see this here as the second log.
All right, now to take it even further,
let's actually do another read file, but instead of this,
so that I can show you we can basically do
multiple steps, one after the other, with callbacks.
So, steps that depend upon the result of the previous step.
Okay, so that's why actually in the start file,
I have read this
because then there is a file called read this,
which has the content that we're actually interested in.
Okay?
So, what I'm gonna to do here is to copy this code,
and put it in here.
I'm gonna call this one data one, and then data two,
and the result of the second step, so the second file read,
will depend on the first one.
That's because we will use the data for file name, remember?
So, here we are doing a (mumbles) now
because we need to put in that variable, and it is called
data one.
Okay, make sense?
So, data one will be read this, okay,
and so then, in the next step, we read txt/readthis.txt,
which is then this.
Okay, and so that's why this file name here is
the same as this content.
And so, that's logged through console data to that.
And, let's quickly test if this works,
and indeed, so that is the content of read this.txt.
And, now I'm actually gonna take it one step further even
because there's some other text in this append file
that I want to add to this first string,
so there's text coming from the other file.
And so, we have yet another step
that depends on the previous step,
so what I'm gonna do is to add another read file in here.
So, just like this.
So, this one is called append,
and I'm gonna call this one the data three, data three here,
and so that's, again, run that.
And, okay, so now we have these two results here.
All right, and now finally, as the last step,
I want to write these two strings together
into a file, okay?
So far, we have only read files,
but I want to write a file as well,
so let's do that right here as well.
So, fs.writeFile,
and of course, we're not using the synchronous one
like we did before,
but again we use, just like here and here and here,
we use the asynchronous version, not the synchronous one.
So, txt slash, missing this one here,
final.
Then, we should add the texting coding here as well,
and then this one also accepts a callback function,
but in this case there is no data that we read,
and so, we don't need two arguments.
So, the only argument that we have is the error, actually.
Okay, so here we have the error, and the data that was read,
but here in writeFile, there is no data.
All that there is, or can be, is an error, okay?
And actually, we're missing something here,
which is what we actually want to write to the file.
Okay, and so that is the second argument,
and what that is, is data two and data three.
So, again a (mumbles) string here,
data two,
then a new line character, which again, is backslash n,
and then data 3.
All right, and so, just like with the read file functions,
then this callback is what's run at the end,
so what I'm gonna do here is to simply log through console
that the files have been written,
or that the file has been written.
Your file has been written,
and let's just use some fun emoji here,
just to make the console a bit brighter for us,
and I think we should be done like this.
So, let's clear the console one more time, run it,
and indeed we see your file has been written.
So, has it really?
Final.
Oh, yeah, here it is.
So, that is the read this text,
and the append text, both together, both in the same file.
Okay, so that is how we perform multiple steps in orders,
using callback functions, right?
Because imagine that you simply did the same file read,
and then the second file read, so this one,
right after that.
Well, how would you then get access to the data
from the first one, right?
And so, that is how this pattern emerges.
It actually has it's own name,
and I think I mentioned that in the last video,
it is the called callback hell,
and there are some solutions to make this code here
more readable and better to understand,
but for now, that doesn't matter at all for you.
What matters is that Node JS is built around
this philosophy of callbacks,
so that is how Node JS implements asynchronous operations,
by calling callbacks as soon as the operation
that it's doing has been finished.
And, by the way, this way of writing function
that you see here, again,
in case you're not familiar with it,
it is the new ES6 syntax as well, okay?
So, again, I hope that you are familiar
with ES6 at this point,
and so that all of this makes complete sense to you.
If you were to write this function here
without the error function syntax, we would do
simply like this, function, err, data one,
and then like this.
So, that is a normal function,
let's say an old-fashioned function,
and the new version works like this.
The difference between them is mainly the syntax,
but also the fact that an error function,
so this kind of function,
doesn't get it's own disk keyword,
so it uses the disk keyword from the parent function.
And, that is called the lexical disk keyword,
while a normal function like this one always gets
its own disk keyword, right?
I'm sure you're familiar with that kind of stuff,
but just doing a small review here in case you're not.
Okay, I hope that made since.
We did actually never use this error,
we didn't handle any errors,
so, for example, imagine that this file here did not exist.
Well we could have used this error,
and let's actually do that, but just for this one here,
so I don't wanna create all of these error handlers here,
but just in this situation, let's say there was an error,
and so let's say if error,
the return from this function, so do nothing else,
and log to the console,
error, and then we can add some other emoji here,
like this explosion, so like something exploded here.
So, let's now change this here, like start.txt,
run this again,
and so, we have this error now,
so it gives us this log to the console,
and since we did return, it will not do anything after that,
so all of this is basically ignored and will not run,
which is exactly what we want.
Right, but if we put it back to normal,
and then run it again,
well then, everything works just like before.
So, get used to this pattern of callbacks
because you will see it all over the place in Node JS
and throughout this section.