learnyounode icon indicating copy to clipboard operation
learnyounode copied to clipboard

coding style questions about first async io

Open Hillsie opened this issue 8 years ago • 2 comments

I've completed the first asyc challenge and have a few questions. Please see inline commentary:

  • My error handling is basic. What would be a good way to catch if someone hadn't entered a file argument?
  • Is there a better way to write this asynchronously? I saw a TedTalk where (the Godfather) Linus said it was bad taste to use an if statement. Perhaps it was contextual, but could this be written with better taste? perhaps a While ?
  • What is good practice. Console.log here or console.log in the global context?
var fs = require('fs'); 

function countNewLines(){

    fs.readFile(process.argv[2], 'utf8', function doneReading(err, fileContents) {

        /*  My error handling is basic.  What would be a good way to catch if someone 
            hadn't entered a file argument? 
            Is there a better way to write this asynchronously? I saw a TedTalk
            where (the Godfather) Linus said it was bad taste to use an if statement, perhaps
            contextual to his example ,but could this be written with better taste ? ..a While ? */

        if (err) throw err;
        else {
            var countNewLineChar = fileContents.split('\n').length -1;

        /*  what is good practice. Console.log here or console.log in the 
            global context? */

            console.log(countNewLineChar);
        };
    });
};

countNewLines(); 

Hillsie avatar Apr 18 '16 03:04 Hillsie

For instance:


var fs = require('fs'); 

function countNewLines(){

    fs.readFile(process.argv[2], 'utf8', function doneReading(err, fileContents) {

        /*  My error handling is basic.  What would be a good way to catch if someone 
            hadn't entered a file argument? 
            Is there a better way to write this asynchronously? I saw a TedTalk
            where (the Godfather) Linus said it was bad taste to use an if statement, perhaps
            contextual to his example ,but could this be written with a while ? */

        while (!err) {
            var countNewLineChar = fileContents.split('\n').length -1;

        /*  what is good practice. Console.log here or console.log in the 
            global context? */

            console.log(countNewLineChar);
            return;
        };
    });
};

countNewLines();

Hillsie avatar Apr 18 '16 03:04 Hillsie

The callback here is called exactly once. Either an error happen or you received your data, not both. You can improve your error handling by checking the code property. For example, checking if (err && err.code === 'ENOENT') will tell you that the argument you received is a non-existent file location.

Where you decide to use console.log is not strictly important except that the data must be in scope. When doing async work, you can't really put the console.log in global scope. You can keep it as close as possible for readability sake, but this is your choice. Here is what you might have done if you wanted this code to be highly flexible (and thus reusable).

var fs = require('fs');

function countNewLines(filename, callback) {
   fs.readFile(filename, 'utf8', function(err, contents) {
      if (err) return callback(err); // or better error checking if needed

      var count = contents.split('\n').length - 1;

      callback(null, count);
   });
}

countNewLines(process.argv[2], function(err, count) {
   if (err) return console.error(err);

   console.log(count);
});

That is probably pretty useless, but hopefully you see how it allows consumers of countNewLines to do what they need. The "http collect" exercise is a bit of a better example. Making a flexible function allows that same function to be used in the "juggling async" exercise.

--

P.S. I lied earlier. You might receive both an error and data in your callback. However, if you get an error at all, consider any data you received to be invalid.

CodeMan99 avatar Feb 27 '18 02:02 CodeMan99