3

I'm using bluebird to init various type of db connections.

// fileA.js
Promise.all(allConnectionPromises)
    .then(function (theModels) {
        // then i want to do module.exports here
        // console.log here so the expected output
        module.exports = theModels
    })

So that I can require that file above from another file. however if I do that, i get {}.

let A = require('./fileA')  // i get {} here

Any idea how to do this?

Tuan Anh Tran
  • 6,807
  • 6
  • 37
  • 54

1 Answers1

6

You can't magically make an async operation into a synchronous operation in Javascript. So, an async operation will require async coding techniques (callbacks or promises). The same is true in regular coding as in module startup/initialization.

The usual design pattern for dealing with this issue is to give your module a constructor function that you pass a callback to and when you call that constructor function, it will call the callback when the async result is done and then any further code that uses that async result must be in that callback.

Or, since you're already using promises, you can just export a promise that the calling code can use.

// fileA.js
module.exports = Promise.all(allConnectionPromises);

Then, in code that uses this:

require('./fileA').then(function(theModels) {
    // access theModels here
}, function(err) {
    console.log(err);
});

Note, when doing it like this, the exported promise serves as a convenient cache for theModels too since every other module that does require('./fileA') will get the same promise back and thus the same resolved value without re-executing the code behind getting the models.


Though I think the promises version is probably cleaner especially since you're already using promises within the module, here's what the constructor version would look like for comparison:

// fileA.js
var p = Promise.all(allConnectionPromises);

module.exports = function(callback) {
   p.then(function(theModels) {
       callback(null, theModels);
   }, function(err) {
       callback(err);
   });
}

Then, in code that uses this:

require('./fileA')(function(err, theModels) {
    if (err) {
        console.log(err);
    } else {
        // use theModels here
    }
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Hi, that would make using it quite hard. Preferably , i would want something like `var models = require('./models')` if possible. – Tuan Anh Tran Jan 25 '16 at 04:55
  • 1
    @TuanAnhTran - as I've already said in my answer, you can't get an async value synchronously. You just can't. Part of learning to program in node.js is learning to program with async IO and how to do so efficiently and cleanly. You will need to do that in this case. It generally means changing things to move the code that you wanted to be after the `require()` statement to just be inside the callback that delivers the data. That's how you program with async results. Welcome to the async world of node.js programming. – jfriend00 Jan 25 '16 at 05:45