0

I am trying to understand how asynchronous functions are used.

As an assigement I have to turn the following function:

var fs = require('fs');

function calculateByteSize(){
    var totalBytes = 0,
    i,
    filenames,
    stats;

    filenames = fs.readdirSync(".");
    for (i = 0; i < filenames.length; i++){
        stats = fs.statSync("./" + filenames[i]);
        totalBytes += stats.size;
    }
    console.log(totalBytes);
}
calculateByteSize();

Into its asynchronous version.

So far I got:

var fs = require('fs');

function calculateByteSize(){
    var totalBytes = 0,
    i,
    stats;
    fs.readdir(".", function(err, data){
        for (i = 0; i < data.length; i++){
            fs.stat("./" + data[i],function(err, stats){
                 totalBytes += stats.size;
            }); 
        }
    });
    console.log(totalBytes);
}

calculateByteSize();

Which works-- if I print the values of 'totalBytes' during the for cycle, I get the correct values.

However, the console.log statement prints the value '0', as it seems it get executed before the cycle.

Everything works fine if I use statSync as in the original function.

My question is: given the choice between a synchronous and asynchronous version of a function, which is best to use when nested into an asynchronous function?

Is there a way can I make sure my print statement is executed after the correct value is generated, without using a promise? (as in: Issue with nested asynchronous function not returning data in time)

Community
  • 1
  • 1
Ferduun
  • 137
  • 13
  • Have you read [How to return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Jasen Oct 07 '15 at 19:32

1 Answers1

1

Using the asynchronous version of an IO-bound operation in node is ideal since the environment is singly-threaded and runs on an event loop. By doing this, you don't block the event loop and wait on the IO (in this case to the filesystem). While you are doing this filesystem call, the event loop can continue and do other useful work (for example - accepting additional HTTP requests in the case of an HTTP server).

Here's how you can log the total bytes only after all of them have been added up and without a promise:

function calculateByteSize(){
  var totalBytes = 0,
      statsCallsCompleted = 0,
      i,
      stats;

  fs.readdir(".", function (err, data) {
    for (i = 0; i < data.length; i++){
      fs.stat("./" + data[i], function (err, stats) {
        statsCallsCompleted += 1;
        totalBytes += stats.size;
        if (statsCallsCompleted === data.length) {
          console.log('Total Bytes:', totalBytes);
        }
      }); 
    }
  });
}
Vinay
  • 6,204
  • 6
  • 38
  • 55