簡體   English   中英

帶有config的NodeJS模塊 - 從require或from module.exports實例化

[英]NodeJS Module with config - instantiate from require or from module.exports

我正在開發一個具有多個功能的node.js模塊。
模塊本身將需要一些配置啟動(將有默認值...可以被覆蓋 - 例如文件路徑)

導出函數時首選方法是什么? 允許它從require語句實例化,並將配置對象(可選)傳遞給構造函數?

var MyModule = require('myModule);

var myModule = new MyModule({
    name: "test name"
});

myModule.doThing(function(x){

});

在模塊中有這個:

module.exports = function MyModule(){
        MyModule.prototype.config = {name: "default name"}

            function doThing(cb){
                //do stuff
                cb();
            }
}

或者,從模塊中的exports語句創建實例,然后像這樣使用它:

var myModule = require('myModule);

myModule.config = {name: "test name"}

myModule.doThing(function(x){

});

相反,在模塊中有這個:

module.exports = exports = MyModule();

function MyModule(){
MyModule.prototype.config = {name: "default name"}

    function doThing(cb){
        //do stuff
        cb();
    }
}

我會說讓用戶在實例化時提供一個對象,將默認值放在原型中。 您可能還希望提供配置功能,這允許您(現在或將來)驗證鍵/值,並允許您的用戶在實例化后設置配置。

// Module

var Mod = module.exports = function Mod (opts) {
  opts = (opts === Object(opts)) ? opts :  {};

  // This allows users to instanciate without the `new` keyword
  if (! (this instanceof Mod)) {
    return new Mod(opts);
  }

  // Copy user provided configs to this.config
  for (var key in opts) if ({}.hasOwnProperty.call(opts, key)) {
    this.config[key] = opts[key];
  }
};

Mod.prototype.config = {
  foo : 'foo',
  bar : 'bar'
};

Mod.prototype.configure = function configure (key, val) {
  this.config[key] = val;
  return this;
};

// Usage

const Mod = require('/path/to/mod');

var i1 = new Mod;

var i2 = Mod();

var i3 = new Mod({
  foo: 'bar'
});

var i4 = Mod({
  foo: 'bar'
});

i4.configure('bar', 'baz');

var i5 = (new Mod).configure('bar', 'baz');

編輯

正如Jake Sellers在評論中指出的那樣,這不是CommonJS模塊中的標准API模式。 更好的解決方案是導出一個函數,該函數返回您正在創建的任何對象。

更重要的是 ,我不應該建議將配置放在原型中。 這樣做會使所有子項共享配置對象。 因此,對它的任何修改也會影響所有兒童。 對我感到羞恥,當我寫這個廢話時,我不是初學者。 雙倍謝謝傑克;)

更好的實施:

// Keep defaults private
var defaults = {
  foo : 'foo',
  bar : 'bar'
};

// Construct
var Mod = function Mod (opts) {
  opts = (opts === Object(opts)) ? opts :  {};

  // This allows users to instanciate without the `new` keyword
  if (! (this instanceof Mod)) {
    return new Mod(opts);
  }

  this.config = {};
  // Copy user provided configs to this.config or set to default
  for (var key in defaults) if (defaults.hasOwnProperty(key)) {
    if ({}.hasOwnProperty.call(opts, key)) {
      this.config[key] = opts[key];
    }
    else {
      this.config[key] = defaults[key];
    }
  }
};

// Let the user update configuration post-instanciation
Mod.prototype.configure = function configure (key, val) {
  this.config[key] = val;
  return this;
};

// Export a function that creates the object
exports.createMod = function createMod (opts) {
  return new Mod(opts);
};

// Export the constructor so user is able to derive from it
// or check instanceof
exports.Mod = Mod;

// USAGE

var mod = require('/path/to/mod');

var i1 = mod.createMod({ foo : 'bar' });

i1.configure('bar', 'baz');

這取決於您是否希望模塊的用戶能夠使用一個預定義的實例(您在module.exports創建的module.exports ),或者您希望它們能夠創建自己的實例(那么您需要將構造函數導出為函數,而不是其返回值)。

如果你去寫一個構造函數,我會選擇第二個選項(讓用戶創建實例) - 除非它是你提供的單例對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM