Bartlomiej Lewandowski Bartlomiej Lewandowski - 2 months ago 17
Javascript Question

Export a variable which is a result of an asynchronous function call

I'm creating an app that will use the https://github.com/vpulim/node-soap to communicate with a soap server.

I would like to create a client component which I will forward the necessary methods to the soap-client created with this module.

I'm having trouble to return an object that will use this client, since the client is created asynchronously.

var soap = require('soap');
var url = 'http://someurl?wsdl';

soap.createClient(url, function(err, client) {
if (err) {
console.log(err);
return;
}
console.log(client.describe());
// I need to publish this client so that other functions in this file will be able to use it
});



module.exports = {
doSomething: function() {
//how can I access the client here?
}
};


How would I go about doing this?

Answer

One solution to this problem is to use promises:

var soap = require('soap');
var url = 'http://someurl?wsdl';

var clientPromise = new Promise(function(resolve, reject) {
    soap.createClient(url, function(err, client) {
        if (err) {
            // reject the promise when an error occurs
            reject(err);
            return;
        }

        // resolve the promise with the client when it's ready
        resolve(client);
    });
});


module.exports = {
    doSomething: function() {
        // promise will wait asynchronously until client is ready
        // then call the .then() callback with the resolved value (client)
        return clientPromise.then(function(client) {
             // do something with client here
        }).catch(function(err) {
             // handle errors here
             console.error(err);
        });
    }
};

A few advantages to this:

  • Promises are native JavaScript objects (as of Node 4.0.0, with packages such as bluebird providing support for prior versions)
  • Promises can be "reused": if clientPromise has already resolved once, it will immediately resolve when doSomething is later called.

Some disadvantages:

  • doSomething and all other exported functions are inheritly asynchronous.
  • Is not directly compatible with Node-type callbacks.