简体   繁体   中英

Node.js module sync to async

I have a simple Node.js module that takes a directory of Handlebars templates, compiles them and then exports an object of them keyed on their name:

'use strict';

var
  fs = require('fs'),
  path = require('path'),
  handlebars = require('handlebars'),
  templateDir = __dirname + '/templates/',
  templates = {};

fs.readdirSync(templateDir).forEach(function (file) {
  templates[path.basename(file, path.extname(file))] =
    handlebars.compile(fs.readFileSync(templateDir + file));
});

module.exports = templates;

So then in other modules I can just:

var templates = require('./templates');

templates[SOME_TEMPLATE]({ ... });

I'm struggling on how to do this asynchronously though, specifically how to export with an emitter in the mix.

var emitter = require('events').EventEmitter;

module.exports = function (callback) {
  emitter.on('templates-compiled', function () {
    callback(templates);
  });

  callback();
};

fs.readdir(templateDir, function (err, files) {
  if (!err) {
    files.forEach(function (file) {
      fs.readFile(templateDir + file, function(err, data) {
        if (!err) {
          templates[path.basename(file, path.extname(file))] =
            handlebars.compile(data);

          if (files[files.length - 1] === file) {
            emitter.emit('templates-compiled');
          }
        } else {
        }
      });
    });
  } else {
  }
});

Heres a modification of the above that works:

var EventEmitter = require('events').EventEmitter;
var path = require('path');
var fs = require('fs');

module.exports = function(dir, callback) {

  var emitter = new EventEmitter();
  var templates = {};

  emitter.on('templates-compiled', function(t) {
    callback(null, t);
  });

  emitter.on('templates-error', function(e) {
    callback(e);
  });

  fs.readdir(dir, function(err, files) {
    if (!err) {
      files.forEach(function(file) {
        fs.readFile(path.join(dir, file), function(err, data) {
          if (!err) {
            //note: i'm just calling toString() here - do your compile here instead
            templates[path.basename(file, path.extname(file))] = data.toString();
            if (files[files.length - 1] === file) {
              emitter.emit('templates-compiled', templates);
            }
          } else {
            emitter.emit('templates-error', err);
          }
        });
      });
    } else {
       emitter.emit('templates-error', err);
    }
  });
};

However you may want to look at using q or async to trim down the pyramid of doom .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM