Skip to content
Matt BertiMatt BertiMatt BertiMatt Berti

Matt Berti

Using the async module

Node.js is primed for asyncronous operations. Although there are syncronous operations available like fs.readFileSync, synchronous functions should only be used during startup, or when your module is initially loaded, and never after that.

Building asyncronous code can be tricky, but the async module can help.

For example, if you wanted to get the contents of more than one file, you may do it like so:

var files = ['meta.json', 'article.md'],
    data = {};

readFiles(files);

function readFiles (files, callback) {
  fs.readFile (files[0], 'utf8', function (err, content) {
    if (err) return err;
    data[files[0]] = content;
    fs.readFile (files[1], 'utf8', function (err, content) {
      if (err) return err;
      data[files[1]] = content;
      callback();
    }
  }
}

But with async, you can run the asyncronous functions in parallel with an optional callback method after the functions have completed.

var async = require('async');

async.parallel({
  foo: function (cb) {
    fs.readFile ('meta.json', 'utf8', function (err, content) {
      if (err) return cb(err);
      cb (null, content);
    });
  },
  bar: function (cb) {
    fs.readFile ('article.md', 'utf8', function (err, content) {
      if (err) return cb(err);
      cb (null, content);
    });
  }
}, function (err, results) {
  console.log("Async fin.", results);
})

Running middleware or API calls in turn can instead be run in parallel can speed up response time in a big way.[1]

So instead of:

app.use(getUser);
app.use(getSiteList);
app.use(getCurrentSite);
app.use(getSubscription);

... we could do something like this:

function parallel(middlewares) {
  return function (req, res, next) {
    async.each(middlewares, function (mw, cb) {
      mw(req, res, cb);
    }, next);
  };
}

app.use(parallel([
  getUser,
  getSiteList,
  getCurrentSite,
  getSubscription
]));

  1. 5 steps to making a Node.js frontend app 10x faster ↩︎