Skip to content Skip to sidebar Skip to footer

Executing Asynchronous Calls In A Synchronous Manner

I've been trying to wrap my head around this issue for the last hours but can't figure it out. I guess I still have to get used to the functional programming style ;) I wrote a rec

Solution 1:

Look for Step module. It can chain asynchronous functions calls and pass results from one to another.

Solution 2:

You could use async module . Its auto function is awesome . If you have function A() and function B() and function C() . Both function B() and C() depend of function A() that is using value return from function A() . using async module function you could make sure that function B and C will execute only when function A execution is completed .

Ref : https://github.com/caolan/async

async.auto({
            A: functionA(){//code here },B: ['A',functionB(){//code here }],
            C: ['A',functionC(){//code here }],
            D: [ 'B','C',functionD(){//code here }]
        }, function (err, results) {
              //results is an array that contains the results of all the function defined and executed by async module// if there is an error executing any of the function defined in the async then error will be sent to err  and as soon as err will be produced execution of other function will be terminated
            }
        })
    });

In above example functionB and functionC will execute together once function A execution will be completed . Thus functionB and functionC will be executed simultaneously

functionB: ['A',functionB(){//code here }]

In above line we are passing value return by functionA using 'A'

and functionD will be executed only when functionB and functionC execution will be completed .

if there will be error in any function , then execution of other function will be terminated and below function will be executed .where you could write your logic of success and failure .

function (err, results) {}

On succesfull execution of all function "results" will contain the result of all the functions defined in async.auto

function (err, results) {}

Solution 3:

Take a look at modification of your original code which does what you want without async helper libs.

var fs = require('fs'),
    path = require('path');

functiondo_stuff(name, cb)
{
    console.log(name);
    cb();
}

functionparse(dir, cb) {
    fs.readdir(dir, function (err, files) {
        if (err) {
            cb(err);
        } else {             

            // cb_n creates a closure// which counts its invocations and calls callback on nthvar n = files.length;
            var cb_n = function(callback)
            {
                returnfunction() {
                    --n || callback();
                }
            }

            // inside 'each' we have exactly n cb_n(cb) calls// when all files and dirs on current level are proccessed, // parent cb is called// f = filename, p = pathvar each = function (f, p) {
                returnfunction (err, stats) {
                    if (err) {
                        cb(err);
                    } else {
                        if (stats.isDirectory()) {
                            parse(p, cb_n(cb));
                        } elseif (stats.isFile()) {
                            do_stuff(p+f, cb_n(cb));
                            // if do_stuff does not have async // calls inself it might be easier // to replace line above with//  do_stuff(p+f); cb_n(cb)();
                        }
                    }
                };
            };

            var i;
            for (i = 0; i < files.length; i++) {
                var f = files[i];
                var p = path.join(dir, f);
                fs.stat(p, each(f, p));
            }
        }
    });
}

parse('.', function()
{
    // do some stuff here when async parse completely finishedconsole.log('done!!!');
});

Solution 4:

Something like this would work -- basic change to your code is the loop turned into a recursive call that consumes a list until it is done. That makes it possible to add an outer callback (where you can do some processing after the parsing is done).

var fs = require('fs'),
  path = require('path');

functionparse(dir, cb) {
    fs.readdir(dir, function (err, files) {
        if (err)
          cb(err);
        elsehandleFiles(dir, files, cb);
    });
}

functionhandleFiles(dir, files, cb){
  var file = files.shift();
  if (file){
    var p = path.join(dir, file);
    fs.stat(p, function(err, stats){
      if (err)
        cb(err);
      else{
        if (stats.isDirectory())
          parse(p, function(err){
            if (err)
              cb(err);
            elsehandleFiles(dir, files, cb);
          });
        elseif (stats.isFile()){
          console.log(p);
          handleFiles(dir, files, cb);
        }
      }
    })
  } else {
    cb();
  }

}


parse('.', function(err){
  if (err)
    console.error(err);
  else {
    console.log('do something else');
  }
});

Solution 5:

See following solution, it uses deferred module:

var fs   = require('fs')
  , join = require('path').join
  , promisify = require('deferred').promisify

  , readdir = promisify(fs.readdir), stat = promisify(fs.stat);

function parse (dir) {
    return readdir(dir).map(function (f) {
        returnstat(join(dir, f))(function (stats) {
            if (stats.isDirectory()) {
                return parse(dir);
            } else {
                // do some stuff
            }
        });
    });
};

parse('.').done(function (result) {
    // do some stuff here when async parse completely finished
});

Post a Comment for "Executing Asynchronous Calls In A Synchronous Manner"