2

I am working with Node and I have a "class" that takes a directory as a parameter. It tries to create that directory and if it fails, then it throws an error:

function Config(dir) {
  fs.mkdir(dir, function(err) {
    if(err) throw new Error('Error', err);
  }
}

My question is, is this an approved way of doing this? If I were to use a callback, then the rest of my program would have to reside in that callback, which seems odd to me.

This issue manifested itself when I tried to write a test using mocha which won't work since the exception is thrown in an async call:

it('should throw an error on a bad directory', function() {
  var fn = function() {
    var badConfig = new Config('/asdf');
  };
  assert.throws(fn, Error);
});

I've investigated domains as a way to solve the unit test issue, but that didn't seem to solve my problem (or I didn't implement them correctly).

var d = domain.create().on('error', function(err) { throw err; }
d.run(function() {
  function Config(dir) {
    fs.mkdir(dir, function(err) {
      if(err) throw err;
    }
  }
});

Ultimately, I'm looking for a best practice that allows me to indicate to the application that something bad happened, and allows me to create tests for that solution.

3
  • Asynchronously throwing errors should be avoided, as they cannot be caught [easily]. You will need to use a callback, yes. Commented Feb 17, 2014 at 17:05
  • Maybe also have a look at the pattern I suggested in Javascript Proper Class constructor Commented Feb 17, 2014 at 17:06
  • 1
    using asynchronous operations in constructor is an antipattern. Commented Feb 17, 2014 at 17:41

2 Answers 2

2

You have three possibilities:

  1. Using a synchronous call. As AsolBerg explained, your case suits exactly why some fs functions have their synchronous equivalent. It's ok because in your case, all your application depends on one Config instance to be loaded. but there are cases

  2. Using a callback as constructor argument.

  3. If constructor callback sounds really too odd for you, put your initialization code into an init() method, that takes a callback. It's a matter of personnal preference, but rather use this technic.

Last option, you can returns a Future in your init() method. There are several future libraries in NodeJS, that are an elegant alternative to callback parameter. But you can't use it in your constructor... as the constructor's return is the created object.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a complete answer, thanks for listing a couple alternatives. I do use Q elsewhere in my program but since the program should not continue if the creation of this object fails, I'm opting to go the synchronous route.
0

It sounds like in this case you might actually want to make a synchronous call (e.g. the rest of your application depends on this call being finished before proceeding). So although its normally not the way you want to think about building your node apps you could use the synchronous version mkdirSync().

http://nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode

Then if the call fails you can catch the error and return it and (probably) exit the app.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.