简体   繁体   English

Node.js使所有模块中的初始化对象可用

[英]Node.js make initialized object available in all modules

I have an initialized object that I initialized in app.js file and I would like to make this initialized object is available in all modules. 我有一个初始化的对象,我在app.js文件中初始化,我想使这个初始化对象在所有模块中都可用。 How could I do that? 我怎么能这样做? Passing this object to every modules is one way to do and I'm wondering if I'm missing anything or there should be done in difference ways? 将这个对象传递给每个模块是一种方法,我想知道我是否遗漏了什么,或者应该以不同的方式完成?

I saw mongoose actually support default connection, which I need to init in app.js one time and anywhere in other modules, I can just simply use it without requiring passing it around. 我看到mongoose实际上支持默认连接,我需要在app.js中初始化一次和其他模块中的任何地方,我可以简单地使用它而不需要传递它。 Is there any I can do the same like this? 有没有我可以像这样做?

I also checked global object doc from node.js http://nodejs.org/api/globals.html , and wondering I should use global for issue. 我还检查了node.js http://nodejs.org/api/globals.html中的全局对象文档,并想知道我应该使用global来解决问题。

Thanks 谢谢

A little advice: 一点建议:

  • You should only very rarely need to use a global. 你应该很少需要使用全局。 If you think you need one, you probably don't. 如果你认为你需要一个,你可能不需要。
  • Singletons are usually an anti-pattern in Node.js, but sometimes (logging, config) they will get the job done just fine. 单身人士通常是Node.js中的反模式,但有时(日志,配置)他们将完成工作。
  • Passing something around is sometimes a useful and worthwhile pattern. 传递一些东西有时是一种有用且有价值的模式。

Here's an example of how you might use a singleton for logging: 以下是如何使用单例进行日志记录的示例:

lib/logger.js LIB / logger.js

var bunyan = require('bunyan'),
  mixIn = require('mout/object/mixIn'),

  // add some default options here...
  defaults = {},

  // singleton
  logger,

  createLogger = function createLogger(options) {
    var opts;

    if (logger) {
      return logger;
    }

    opts = mixIn({}, defaults, options);

    logger = bunyan.createLogger(opts);

    return logger;
  };

module.exports = createLogger;

lib/module.js LIB / module.js

var logger = require('./logger.js'),
  log = logger();

log.info('Something happened.');

Hope that helps. 希望有所帮助。

The solution, as you suggest is to add the object as a property to the global object. 正如您所建议的那样,解决方案是将对象作为属性添加到全局对象。 However, I would recommend against doing this and placing the object in its own module that is require d from every other module that needs it. 但是,我建议不要这样做并将对象放在自己的模块中,该模块require来自需要它的每个其他模块。 You will gain benefits later on in several ways. 您将在以后以多种方式获益。 For one, it is always explicit where this object comes from and where it is initialized. 首先,它始终是显式对象来自何处以及初始化的位置。 You will never have a situation where you try to use the object before it is initialized (assuming that the module that defines it also initializes it). 在初始化之前,您将永远不会尝试使用该对象(假设定义它的模块也初始化它)。 Also, this will help make your code more testable, 此外,这将有助于使您的代码更易于测试,

There are multiple solutions to the problem, depends upon how large your application is. 该问题有多种解决方案,取决于您的应用程序的大小。 The two solutions that you have mentioned are the most obvious ones. 你提到的两个解决方案是最明显的解决方案。 I would rather go for the third which is based on re-architecturing your code. 我宁愿选择第三个基于重新构建代码的方法。 The solution that I am providing looks alot like the executor pattern. 我提供的解决方案看起来很像执行程序模式。

First create actions which require your common module that are in this particular form - 首先创建需要您使用此特定形式的公共模块的操作 -

var Action_One = function(commonItems) {
    this.commonItems = commonItems;
};

Action_One.prototype.execute = function() {
    //..blah blah
    //Your action specific code
};


var Action_Two = function(commonItems) {
    this.commonItems = commonItems;
};

Action_Two.prototype.execute = function() {
    //..blah blah
    //Your action_two specific code
};

Now create an action initializer which will programmatically initialize your actions like this - 现在创建一个动作初始化程序,它将以编程方式初始化您的动作,如下所示 -

var ActionInitializer = function(commonItems) {
    this.commonItems = commonItems;
};

ActionInitializer.prototype.init = function(Action) {
    var obj = new Action(this.commonItems);
    return obj;
};

Next step is to create an action executor - 下一步是创建一个动作执行器 -

//You can create a more complex executor using `Async` lib or something else
var Executor = function(ActionInitializer, commonItems) {
    this.initializer = new ActionInitializer(commonItems);
    this.actions = [];
};
//Use this to add an action to the executor
Executor.prototype.add = function(action) {
    var result = this.initializer.init(action);
    this.actions.push(result);
};
//Executes all the actions 
Executor.prototype.executeAll = function() {
    var result = [];
    for (var i = this.action.length - 1; i >= 0; i--) {
        result[i] = this.action[i].execute();
    }
    this.action = []
    return result;
};

The idea was to decouple every module so that there is only one module Executor in this case which is dependent on the common properties. 我们的想法是将每个模块分离,以便在这种情况下只有一个模块Executor依赖于公共属性。 Now lets see how it would work - 现在让我们看看它是如何工作的 -

var commonProperties = {a:1, b:2};
//Pass the action initilizer class and the common property object to just this one module
var e = new Executor(ActionInitializer, commonProperties);
e.add(Action_One);
e.add(Action_Two);
e.executeAll();
console.log(e.results);

This way your program will be cleaner and more scalable. 这样,您的程序将更清晰,更具可扩展性。 Shoot questions if it's not clear. 如果不清楚则拍摄问题。 Happy coding! 快乐的编码!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM