0

I am new to node and I'm currently wrestling with finding the most iodomatic way to create an object whose construction depends on the results of an http query. The object is useless until the query is returned and parsed successfully so it feels wrong to return from the constructor without my object being initialized but everything I've read about node says I should keep things asynchronous.

I could either write it synchronously like this (pardon the pseudocode)

function FooConfig(cfg_url) {
  // use httpsync to get the response synchronously
  var response = get(cfg_url);

   if (response.is_good()) {
     // parse response and set member data from response
     this.bar = response.bar
   } else {
     // Raise an error
   }
};

or asynchronously

function FooConfig(cfg_url) {
  // Use the regular http module and make the request asynchronously
  var newCfg = this;
  http.get(cfg_url, function(response) {
    if (response.is_good()) {
      newCfg.bar = respsonse.bar
    } else {
      // Raise an error
    }
  });
});

The problem with the async version is that any client code that depends on an instance of FooCfg might fail if the request is not completed.

i.e.

var myCfg = new FooCfg('www.someurl.com/config')
// request is still pending
var myDependentObject = new DependsOnConfig(cfg); // Error, this neeeds myCfg.bar

Is this an instance where its ok to be synchronous? this should only happen once when the node application is being initialized.

mjn12
  • 1,853
  • 3
  • 19
  • 27

2 Answers2

1

I would use a Factory for this. Basically, instead of doing your async fetch inside your constructor, do it in a factory method and pass the results of your fetch to the constructor instead. Then, pass back the new object via a callback.

So, your constructor might look something like this:

function FooConfig(cfg_data) {
    this.bar = cfg_data.bar
}

And your factory method would look something like:

var fooFactory(callback) {
    http.get(cfg_url, function(response) {
        if (response.is_good()) {
            callback(null, new FooConfig(response)) // Here's the actual constructor call
        } else {
            callback(new Error("something bad happened"))
        }
    });
}

You'd call it like:

fooFactory(function(err, myCfg) {
    if (err) {
        // handle error
    } else {
        var myDependentObject = new DependsOnConfig(myCfg);
    }
});
Mike S
  • 41,895
  • 11
  • 89
  • 84
-1

I would split construction and initialisation into two different parts, and have the initialisation method return a promise, or at least a callback. when the initialisation is done, then use it.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Do you mean like in @MikeS' answer, or to have an `init` method that takes a callback/returns a promise and leaves the instance unusable until then? – Bergi Oct 27 '14 at 18:25