Viewed   4.3k times

I'm kinda new to module creation and was wondering about module.exports and waiting for async functions (like a mongo connect function for example) to complete and exporting the result. The variables get properly defined using async/await in the module, but when trying to log them by requiring the module, they show up as undefined. If someone could point me in the right direction, that'd be great. Here's the code I've got so far:

// module.js

const MongoClient = require('mongodb').MongoClient
const mongo_host = '127.0.0.1'
const mongo_db = 'test'
const mongo_port = '27017';

(async module => {

  var client, db
  var url = `mongodb://${mongo_host}:${mongo_port}/${mongo_db}`

  try {
    // Use connect method to connect to the Server
    client = await MongoClient.connect(url, {
      useNewUrlParser: true
    })

    db = client.db(mongo_db)
  } catch (err) {
    console.error(err)
  } finally {
    // Exporting mongo just to test things
    console.log(client) // Just to test things I tried logging the client here and it works. It doesn't show 'undefined' like test.js does when trying to console.log it from there
    module.exports = {
      client,
      db
    }
  }
})(module)

And here's the js that requires the module

// test.js

const {client} = require('./module')

console.log(client) // Logs 'undefined'

I'm fairly familiar with js and am still actively learning and looking into things like async/await and like features, but yeah... I can't really figure that one out

 Answers

5

You have to export synchronously, so its impossible to export client and db directly. However you could export a Promise that resolves to client and db:

module.exports = (async function() {
 const client = await MongoClient.connect(url, {
   useNewUrlParser: true
 });

  const db = client.db(mongo_db);
  return { client, db };
})();

So then you can import it as:

const {client, db} = await require("yourmodule");

(that has to be in an async function itself)

PS: console.error(err) is not a proper error handler, if you cant handle the error just crash

Friday, September 9, 2022
 
5

A year and some later, here is the best information I've found on the subject.

There are 4 types of exports. Here are usage examples of each, along with some imports that use them:

Export Syntax

// default exports
export default 42;
export default {};
export default [];
export default (1 + 2);
export default foo;
export default function () {}
export default class {}
export default function foo () {}
export default class foo {}

// variables exports
export var foo = 1;
export var foo = function () {};
export var bar;
export let foo = 2;
export let bar;
export const foo = 3;
export function foo () {}
export class foo {}

// named exports
export {};
export {foo};
export {foo, bar};
export {foo as bar};
export {foo as default};
export {foo as default, bar};

// exports from
export * from "foo";
export {} from "foo";
export {foo} from "foo";
export {foo, bar} from "foo";
export {foo as bar} from "foo";
export {foo as default} from "foo";
export {foo as default, bar} from "foo";
export {default} from "foo";
export {default as foo} from "foo";

Import Syntax

// default imports
import foo from "foo";
import {default as foo} from "foo";

// named imports
import {} from "foo";
import {bar} from "foo";
import {bar, baz} from "foo";
import {bar as baz} from "foo";
import {bar as baz, xyz} from "foo";

// glob imports
import * as foo from "foo";

// mixing imports
import foo, {baz as xyz} from "foo";
import foo, * as bar from "foo";

// just import
import "foo";

Source.

Friday, November 18, 2022
 
3

To be more specific:

module is the global scope variable inside a file.

So if you call require("foo") then :

// foo.js
console.log(this === module); // true

It acts in the same way that window acts in the browser.

There is also another global object called global which you can write and read from in any file you want, but that involves mutating global scope and this is EVIL

exports is a variable that lives on module.exports. It's basically what you export when a file is required.

// foo.js
module.exports = 42;

// main.js
console.log(require("foo") === 42); // true

There is a minor problem with exports on it's own. The _global scope context+ and module are not the same. (In the browser the global scope context and window are the same).

// foo.js
var exports = {}; // creates a new local variable called exports, and conflicts with

// living on module.exports
exports = {}; // does the same as above
module.exports = {}; // just works because its the "correct" exports

// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works

Read more about exports

Friday, November 4, 2022
5

Both models are very similar. There are two primary differences, one of which is going away soon (for some definition of "soon").

One difference is that Node.js is asynchronously single-threaded, while ASP.NET is asynchronously multi-threaded. This means the Node.js code can make some simplifying assumptions, because all your code always runs on the same exact thread. So when your ASP.NET code awaits, it could possibly resume on a different thread, and it's up to you to avoid things like thread-local state.

However, this same difference is also a strength for ASP.NET, because it means async ASP.NET can scale out-of-the-box up to the full capabilities of your sever. If you consider, say, an 8-core machine, then ASP.NET can process (the synchronous portions of) 8 requests simultaneously. If you put Node.js on a souped-up server, then it's common to actually run 8 separate instances of Node.js and add something like nginx or a simple custom load balancer that handles routing requests for that server. This also means that if you want other resources shared server-wide (e.g., cache), then you'll need to move them out-of-proc as well.

The other major difference is actually a difference in language, not platform. JavaScript's asynchronous support is limited to callbacks and promises, and even if you use the best libraries, you'll still end up with really awkward code when you do anything non-trivial. In contrast, the async/await support in C#/VB allow you to write very natural asynchronous code (and more importantly, maintainable asynchronous code).

However, the language difference is going away. The next revision of JavaScript will introduce generators, which (along with a helper library) will make asynchronous code in Node.js just as natural as it is today using async/await. If you want to play with the "coming soon" stuff now, generators were added in V8 3.19, which was rolled into Node.js 0.11.2 (the Unstable branch). Pass --harmony or --harmony-generators to explicitly enable the generator support.

Monday, September 19, 2022
 
3

.on('data, ...) does not wait for your await. Remember, an async function returns a promise immediately and .on() is not paying any attention to that promise so it just keeps merrily going on.

The await only waits inside the function, it does not stop your function from returning immediately and thus the stream thinks you've process the data and keeps sending more data and generating more data events.

There are several possible approaches here, but the simplest might be to pause the stream until processData() is done and then restart the stream.

Also, does processData() return a promise that is linked to the completion of the async operation? That is also required for await to be able to do its job.

The readable stream doc contains an example of pausing the stream during a data event and then resuming it after some asynchronous operation finishes. Here's their example:

const readable = getReadableStreamSomehow();
readable.on('data', (chunk) => {
  console.log(`Received ${chunk.length} bytes of data.`);
  readable.pause();
  console.log('There will be no additional data for 1 second.');
  setTimeout(() => {
    console.log('Now data will start flowing again.');
    readable.resume();
  }, 1000);
});
Sunday, December 4, 2022
 
dgvid
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :