Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous nodejs module exports

I was wondering what the best approach is for configuring a module export. "async.function" in the example below could be a FS or HTTP request, simplified for the sake of the example:

Here's example code (asynmodule.js):

var foo = "bar" async.function(function(response) {   foo = "foobar";   // module.exports = foo;  // having the export here breaks the app: foo is always undefined. });  // having the export here results in working code, but without the variable being set. module.exports = foo; 

How can I export the module only once the async callback has been executed?

edit a quick note on my actual use-case: I'm writing a module to configure nconf (https://github.com/flatiron/nconf) in an fs.exists() callback (i.e. it will parse a config file and set up nconf).

like image 806
Brett Avatar asked Nov 27 '13 09:11

Brett


People also ask

Can I export async function?

Answer. This is not possible. Since the value is retrieved asynchronously, all modules that consume the value must wait for the asynchronous action to complete first – this will require exporting a Promise that resolves to the value you want.

How node js modules are exported?

Module exports are the instruction that tells Node. js which bits of code (functions, objects, strings, etc.) to “export” from a given file so other files are allowed to access the exported code. (Don't worry, we'll cover importing code in the next section.) To understand modules in Node.

Is NodeJS require synchronous or asynchronous?

NodeJS is an asynchronous event-driven JavaScript runtime environment designed to build scalable network applications.


2 Answers

Your export can't work because it is outside the function while the foodeclaration is inside. But if you put the export inside, when you use your module you can't be sure the export was defined.

The best way to work with an ansync system is to use callback. You need to export a callback assignation method to get the callback, and call it on the async execution.

Example:

var foo, callback; async.function(function(response) {     foo = "foobar";      if( typeof callback == 'function' ){         callback(foo);     } });  module.exports = function(cb){     if(typeof foo != 'undefined'){         cb(foo); // If foo is already define, I don't wait.     } else {         callback = cb;     } } 

Here async.function is just a placeholder to symbolise an async call.

In main

var fooMod = require('./foo.js'); fooMod(function(foo){     //Here code using foo; }); 

Multiple callback way

If your module need to be called more than once you need to manage an array of callback:

var foo, callbackList = []; async.function(function(response) {     foo = "foobar";      // You can use all other form of array walk.     for(var i = 0; i < callbackList.length; i++){         callbackList[i](foo)     } });  module.exports = function(cb){     if(typeof foo != 'undefined'){         cb(foo); // If foo is already define, I don't wait.     } else {         callback.push(cb);     } } 

Here async.function is just a placeholder to symbolise an async call.

In main

var fooMod = require('./foo.js'); fooMod(function(foo){     //Here code using foo; }); 

Promise way

You can also use Promise to solve that. This method support multiple call by the design of the Promise:

var foo, callback; module.exports = new Promise(function(resolve, reject){     async.function(function(response) {         foo = "foobar"          resolve(foo);     }); }); 

Here async.function is just a placeholder to symbolise an async call.

In main

var fooMod = require('./foo.js').then(function(foo){     //Here code using foo; }); 

See Promise documentation

like image 145
Techniv Avatar answered Sep 29 '22 16:09

Techniv


An ES7 approach would be an immediatly invoked async function in module.exports :

module.exports = (async function(){  //some async initiallizers  //e.g. await the db module that has the same structure like this   var db = await require("./db");   var foo = "bar";    //resolve the export promise   return {     foo   }; })() 

This can be required with await later:

(async function(){    var foo = await require("./theuppercode");   console.log(foo); })(); 
like image 39
Jonas Wilms Avatar answered Sep 29 '22 17:09

Jonas Wilms