FreeCodeCamp and Learning Node: My First Async I/O

Last time we looked at a synchronous program in Node that read a file, split it into lines, and then counted the number of lines using the new line character as a guide.  Today, we’re going to do the same thing, using an asynchronous function, which is a key strength of Node.  If you don’t know what any of this means, well, first, why haven’t you tried this in the Nodeschool tutorial?  Go do that first, I’ll wait.

Next, read on!

Here are the directions and hints.  Once again, remember that the link for the documentation is https://nodejs.org/dist/latest-v6.x/docs/api/:

MY FIRST ASYNC I/O! (Exercise 4 of 13)

  Write a program that uses a single asynchronous filesystem operation to read a file and print the number of newlines it contains to the console (stdout), similar to running cat file | wc -l.

  The full path to the file to read will be provided as the first command-line argument.

 ─────────────────────────────────────────────────────────────────────────────

 # HINTS

  The solution to this problem is almost the same as the previous problem except you must now do it the Node.js way: asynchronous.

  Instead of fs.readFileSync() you will want to use fs.readFile() and instead of using the return value of this method you need to collect the value from a callback function that you pass in as the second argument. To learn more about callbacks, check out:

  [ https://github.com/maxogden/art-of-node#callbacks]

(https://github.com/maxogden/art-of-node#callbacks ).

  Remember that idiomatic Node.js callbacks normally have the signature:

     function callback (err, data) { /* … */ }

  so you can check if an error occurred by checking whether the first argument is truthy. If there is no error, you should have your Buffer object as the second argument. As with readFileSync(), you can supply ‘utf8’ as the second argument and put the callback as the third argument and you will get a String instead of a Buffer.

  Documentation on the fs module can be found by pointing your browser here:

  file:///home/ubuntu/.nvm/versions/node/v4.4.3/lib/node_modules/learnyounode/node_apidoc/fs.html

Now, it says that we are going to do the same thing as last time, only using an asynchronous method rather than a synchronous one.  That means we can use parts of the previous program we wrote.  The first line and the second line, where we call the file system method and assign the file path to a variable, will be the same.

var fs = require(‘fs’);

var filename = process.argv[2];

Line 3 is going to be wildly different, though.  We are using a different method, an asynchronous one, namely fs.readFile().  For an explanation of how the whole asynchronous thing works, the link they gave in the hints (see above) isn’t bad.  Anyway, the readFile() function takes several arguments.  First is the name and path of the file you want to read.  We saved that in ‘filename’.  Second is ‘utf8’, which means you’ll get the info back as text, similar to how we did in the previous program.  Third is where it gets a little weird.  We call an anonymous function – we’ve done this sort of thing before, in the Front End Development exercises, so it shouldn’t be too unfamiliar.  That function is called a ‘callback’ function (see the link they gave for more), and it takes two arguments.  The first is err, so if something goes wrong it will return an error.  The second is called data here, but you could call it contents or something else if you wanted to.  This will be the actual contents of your file (as opposed to the file name and path we stored in ‘filename’).  So, here’s what we have now:

var fs = require(‘fs’);
var filename = process.argv[2];
var bufFile = fs.readFile(filename, ‘utf8’, function callback(err, data) {

});

Now, two questions:

What do we put into that function?

What about the rest of the program from the previous exercise?

Glad you asked!  First, in the function, we want to convert the file to a string, then split it using the ‘\n’ as the separator.  We did this before, so that answers the second question.

I left out the final line, because I wanted to talk briefly about it, and that’s the line where we print the number of new lines to the console.  That HAS to go inside the function.  Why?  Because if you put it at the end, the console.log() will execute while the file is still being read and split.  You’ll get back undefined.  See, this is the whole thing about how asynchronous ops work.  The program can do other stuff while it’s waiting for time sucking operations to complete, and if you put console.log() outside the function, it will be all, “Hey, I can do this while I’m waiting”.  So, inside the function goes console.log(), and we end up with:

var fs = require(‘fs’);
var filename = process.argv[2];
var bufFile = fs.readFile(filename, ‘utf8’, function callback(err, data) {
var strFile = bufFile.toString();
var cnt = strFile.split(‘\n’);
console.log(cnt.length – 1);

});

And there you have it!  Our first Asynchronous I/O program!
Advertisements

2 thoughts on “FreeCodeCamp and Learning Node: My First Async I/O

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s