Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nodejs async module initialization code

I am creating a module dependent on another async one. I'm trying to find the best way to expose my module so that the developer using it finds it intuitive.

Initially my module looked something like this:

var soap = require('soap');

var service = {};
soap.createClient('http://mysoapservice', function(err, client){
    service.myMethod = function(obj, callback){
        //dependency on soap module
        client.soapMethod(obj, function(err, data){
            //do something with the response
            //call other methods etc...
            var res = "processed "+data['name'];
            callback(err, res);
        });
    };
});
module.exports = service;

Of course the problem here is that calling mymethod before the callback inside the module code is reached will throw an exception.

What would be the best pattern to use for such a module?

Is returning promises specific to other libraries (q) an acceptable scenario? or should I just return a callback for when the module is initialized and let the developer handle the rest?

like image 249
adrianvlupu Avatar asked Aug 06 '26 07:08

adrianvlupu


1 Answers

Firstly, I would not use singleton pattern. What if the user wants more than one service? It's better to have a constructor or a factory for this. This provides more design flexibility and makes things clearer for the user. For example:

// constructor
var Service = function() {
     this.initialized = false; // service is not initialized
};

Service.prototype.myMethod = function(...) {
     // check if initialized
     if (!this.initialized)
          return false;
     // do your stuff here
     ...
};

Service.prototype.initialize = function(..., cb) {
     // do your initialization and call the callback
     // also, set this.initialized to true
};

// want to have a factory, to provide a "createService" function?
// no problem
Service.createService = function(..., cb) {
     var service = new Service();
     service.initialize(..., cb);
     // service will only be usable once initialized, but the user
     // can still store a reference to the created object to use
     // in his callback
     return service;
};

module.exports = Service;

Use it like this:

// constructor + initializer
var myService = new Service();
service.initialize(..., function(...) {
    // we have the service, do stuff:
    myService.myMethod(...);
});

// factory method
var myService = Service.createService(..., function(...) {
    // we have the service, do stuff
    myService.myMethod(...);
});

In both cases, calling myMethod() before init will merely return false (instead of throwing).

I like this pattern because it's very similar to other patterns of popular modules out there, so users are used to it and know what to expect.

like image 75
Octav Zlatior Avatar answered Aug 07 '26 22:08

Octav Zlatior