Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 在Node.js中将公共变量传递到单独模块的最佳方式是什么?_Design Patterns_Node.js - Fatal编程技术网

Design patterns 在Node.js中将公共变量传递到单独模块的最佳方式是什么?

Design patterns 在Node.js中将公共变量传递到单独模块的最佳方式是什么?,design-patterns,node.js,Design Patterns,Node.js,我使用单独的路由器文件作为主应用程序和身份验证应用程序的模块。我无法找到将变量(db客户端)传递到路由器的最佳方法。我不想硬编码或通过以下方式传递: module.exports = function(app, db) { 也许使用单例寄存器或使用全局db变量是最好的方法 你对设计模式有什么经验?哪种方式是最好的,为什么?我建议您使用db实例和其他需要全局使用的东西(如“singleton”)创建一个设置文件 例如,我的redis db客户端有settings.js: var redis =

我使用单独的路由器文件作为主应用程序和身份验证应用程序的模块。我无法找到将变量(db客户端)传递到路由器的最佳方法。我不想硬编码或通过以下方式传递:

module.exports = function(app, db) {
也许使用单例寄存器或使用全局db变量是最好的方法


你对设计模式有什么经验?哪种方式是最好的,为什么?

我建议您使用db实例和其他需要全局使用的东西(如“singleton”)创建一个设置文件

例如,我的redis db客户端有settings.js:

var redis = require('redis');
exports.redis = redis.createClient(6379, '127.0.0.1');
在其他多个模块中,我包括:

var settings = require('./settings');
setting.redis.<...>
var设置=需要('./settings');
设置.redis。

很多时候,包括它,我总是有一个db连接实例。

我发现使用依赖注入来传递东西是最好的方式。它看起来确实像你的:

// App.js
module.exports = function App() {
};

// Database.js
module.exports = function Database(configuration) {
};

// Routes.js
module.exports = function Routes(app, database) {
};

// server.js: composition root
var App = require("./App");
var Database = require("./Database");
var Routes = require("./Routes");
var dbConfig = require("./dbconfig.json");

var app = new App();
var database = new Database(dbConfig);
var routes = new Routes(app, database);

// Use routes.
这有很多好处:

    <> LI>强制您将系统划分为具有明显依赖关系的组件,而不是将文件中的依赖项隐藏在文件的中间位置,它们调用“代码>”(“DabaseStudioLeon”)或更糟,<代码> Global。数据库< /代码> .
  • 它使单元测试非常容易:如果我想单独测试
    路由
    ,我可以向它注入伪
    app
    数据库
    参数,并只测试
    路由
    代码本身
  • 它将所有对象图连接放在一个地方,即合成根(在本例中是
    server.js
    ,应用程序入口点)。这为您提供了一个单独的位置来查看系统中的所有内容是如何组合在一起的

我看到的一个更好的解释是,他是一本优秀的书《在.NET中依赖注入》的作者。它同样适用于JavaScript,尤其是Node.js:
require
通常被用作经典的服务定位器,而不仅仅是模块系统。

它完全过时了,但您可以使用
全局
在脚本中:

 global.foo = new Foo();
在另一个脚本中:

 foo.bar();
您还可以使用已经存在的常量:

 Object.foo = new Foo();
在这里:

 Object.foo.bar();

如果使用依赖项注入框架,您可以保存连接模块的所有样板代码

列出了其中的一些。我还建了一个

编辑:下面是一份副本,以备页面更改时使用


require
是Node.js中管理依赖关系的方法,当然它直观有效,但也有其局限性

我的建议是看一下Node.js目前可用的一些依赖注入容器,了解它们的优缺点。其中包括:

仅举几个例子

现在真正的问题是,与简单的
require
相比,Node.js DI容器能实现什么

优点:

  • 更好的可测试性:模块接受它们的依赖项作为输入
  • 控制反转:决定如何在不接触应用程序主代码的情况下连接模块
  • 用于解析模块的可定制算法:依赖项具有“虚拟”标识符,通常它们不绑定到文件系统上的路径
  • 更好的扩展性:由IoC和“虚拟”标识符启用
  • 其他花哨的东西:
    • 异步初始化
    • 模块生命周期管理
    • DI容器本身的可扩展性
    • 能够轻松实现更高级别的抽象(例如AOP)
缺点:

  • 与Node.js的“体验”不同:不使用
    require
    肯定会让人觉得你偏离了Node的思维方式
  • 依赖项与其实现之间的关系并不总是明确的。依赖关系可能在运行时得到解决,并受到各种参数的影响。代码变得更难理解和调试
  • 启动时间较慢
  • 成熟度(目前):目前没有一种解决方案真正流行,因此没有太多教程,没有生态系统,没有经过战斗测试
  • 一些DI容器不能很好地与模块绑定器(如Browserify和Webpack)配合使用

如果我使用下一个代码,则可能重复:`var redis=require('redis');var client=redis.createClient(6379,'127.0.0.1');client.auth(redispass);exports.client=client;`此模块是否会反复重新连接redis?否,仅一次连接。请注意,多次调用require('foo')可能不会导致多次执行模块代码。单例行为依赖于“require”是有风险的,因为只有在传递完全相同的路径时,您才会返回相同的实例。模块基于传递的路径而不是解析的路径进行缓存。换句话说,在您尝试从子目录使用它之前,它将作为一个单例工作。@JollyRoger这不是真的。模块根据其解析的文件名进行缓存。请参阅@Ilya Ok,技术上正确-但这是相对于调用模块的解析文件名,如果从子目录执行,则(根据我的注释)会有所不同。所以,我支持我的“风险”评估。我尝试使用这个例子,但是,既然routes.js在这个routes函数中,我该如何在您的routes.js实现中定义我的路由?谢谢@cpeele00和其他类的方法一样。我也喜欢这种风格。我构建了一个函数,它正好做到了这一点,同时消除了在整个应用程序中传递依赖项所需的手动管道。为了为整个应用程序保留一个单例,最好执行函数app(){…}module.exports=new app();?如果执行此操作,则只缓存新的App(),而不是函数,因此可以确保require()缓存将保留obj