nicholaswmin
nicholaswmin

Reputation: 22949

Passing arguments to Class-based node module

I have this Node.js module structure:

class Foo {

  log() {
    console.log(this.bar); // should log 'hello'
  }
}

module.exports = new Foo;

How can I 'require' the above and pass 'bar' as argument?

E.g something along these lines:

var Foo = require("./foo.js")("hello");

I'm specifically interested in how to do this with Class-based modules.


Update: Class-based Singletons are a Bad Idea™. I've switched to the object-literal module structure instead.

Upvotes: 1

Views: 1583

Answers (3)

Shaybc
Shaybc

Reputation: 3147

Method 1:

create a module that will have only one instance from the class it contains on all modules,

lets call it level-driver.js:

const level = require('level-party'); // used for local lightweight db (google's leveldb) with multi process connection

class LevelDriver
{
    constructor(dbPath)
    {
        // connect to the local leveldb using json schema
        this.db = level(dbPath);
    }
    
    ...
}

// singleton instance holder
let instance = null;

function levelDriver(dbPath)
{
    if(instance == null)
    {
        // create an instance of LevelDriver
        instance = new LevelDriver(dbPath);
    }
    return instance;
}

// export only the instance (not the object) so it will be a singleton
// to all requireing modules (no matter the name or path)
module.exports = levelDriver;

then use it like this:

const levelDriver = require('./level-driver')('./users/users-db'); // manages leveldb connection and actions

Method 2:

const level = require('level-party'); // used for local lightweight db (google's leveldb) with multi process connection

class LevelDriver
{ 
    constructor(dbPath)
    {
        // connect to the local leveldb using json schema
        this.db = level(dbPath);
    }

    ...
}

// export only the instance (not the object) so it will be a singleton
// to all requireing modules (no matter the name or path)
module.exports = (dbPath) => { return new LevelDriver(dbPath) }

then use it like this:

const levelDriver = require('./level-driver')('./users/users-db'); // manages leveldb connection and actions

Upvotes: 0

ant
ant

Reputation: 243

You're mixing class and module definitions. You don't export an instance. You export a definition which you instantiate after you import it. Then you have to call a function

If you're using the ECMA2015 classes, then you can just write:

export default class Foo {
  constructor(bar) {
    this._bar = bar; 
  }

  log() {
    console.log(this._bar);
  }
}

Then your calling code should look like this:

import Foo from './foo.js';
let foo = new Foo('Boom!'); 
foo.log();

The import keyword is used like require in ES5.

Upvotes: 2

Michał Perłakowski
Michał Perłakowski

Reputation: 92511

You can change your foo.js to export the class, not an instance of it, and add a constructor which would assign the first argument to this.bar:

class Foo {
  constructor(bar) {
    this.bar = bar;
  }

  log() {
    console.log(this.bar); // should log 'hello'
  }
}

module.exports = Foo;

Then you can use it like that:

var foo = new (require("./foo.js"))("hello");
foo.log();

Upvotes: 0

Related Questions