节点:如何根据env需要不同的类

在节点中,模块导入(又名require())被硬编码到需要导入的每个文件(又名模块)中。 这可能是几十个或者在我们的情况下有数百个重复的import。 我们以dynamic方式“要求”的主要是服务,例如“playerService”包含查找,更新,获取方法等,但也可以是域对象或持久性库

关键是我们有这个“playerService”js文件的3个版本。 一个在本地(在内存中)进行开发的东西,一个用本地数据库(testing)完成所有工作的东西,一个用API(live)与外部系统完成所有事情的东西。 在这种情况下开关在环境(开发,testing或生活)。

值得注意的是,我们可以在任何地方使用类,因为我们发现返回函数的函数等的函数是不可读/可维护的(我们是java开发人员真正挣扎于js)

我们也专门在我们的节点应用程序中使用web套接字 – 没有http代码。

所以我们的服务如下所示:

const Player = require("./player") class PlayerService { constructor(timeout) { this.timeout= 3000 // todo, put in a config file if (timeout != null) {this.timeout= timeout} } updatePlayer(player) { // logic to lookup player in local array and change it for dev version. // test version would lookup player in DB and update it. } } module.exports = PlayerService 

我们熟悉Grails和Spring的dependency injection,但是还没有发现节点的任何可理解的东西(见下文)。 尽pipe阅读广泛,但我们不是JavaScript,也不是节点大师。

目前我们正在考虑这些选项之一,但希望听到更好的build议:

选项1:

  1. 硬编码“dev”需要,例如require(“./ dev / playerSerice”)
  2. 有一个jenkins生成服务器重写每个文件的源代码要求(“./testing/ playerSerice”)。

选项2:

  1. 硬编码的“dev”要求,例如要求(“./ playerSerice”)
  2. 有一个jenkins构build服务器交换文件/testing/播放器服务/ playerService“./playerService。

显然,这使得开发人员很难在本地机器上运行testing版或专业版,而不会破坏源代码。

选项3: 1.将所需的模块path放在一个configuration文件中。 2.只换出configuration文件。 例如

 let Config = require("./config") let PlayerService = require(Config.playerService) 

我们试图使这个依赖于env,并有一个开发,testing和prodconfiguration的全局configuration骑这些,但没有find一个优雅的方式来做到这一点。 一种方法可能是在每个模块的顶部复制这些代码:

 let env = process.env.NODE_ENV || 'development' let config = require('./config.'+env); let PlayerService = require("./" + Config.playerService) 

然后在config.development.js中:

 var config = require("./config.global") config.PlayerService = "devPlayerService" module.exports = config 

scheme4:也许这样的事情会起作用:

 let env = process.env.NODE_ENV || 'development' require("./" + env + "/playerService") 

上述所有的解决scheme都由于缺乏单例而受到影响 – 服务是无状态的。 我们猜测节点将为每个请求(或者我们的例子中的web套接字消息)构造每个服务的新副本。 有没有办法减less这种情况?

很显然,一些简单,可读且正式维护的dependency injectionforms是很好的,有一些方法可以在注入的类集之间切换。

我们已经阅读了以下文章:

  1. https://blog.risingstack.com/dependency-injection-in-node-js/生成的代码是不可读的(至less对我们来说)。 这样做的例子并没有帮助,团队只是某种用户的代理包装,而不是服务或任何有用的东西。 什么是选项? 为什么select?
  2. https://medium.com/@Jeffijoe/dependency-injection-in-node-js-2016-edition-f2a88efdd427

但发现他们不可理解。 例如,这些例子中的关键词来自于稀薄的空气 – 它们似乎不是JavaScript或者节点的命令,在文档中没有解释它们来自哪里。

并看了这些项目:

  1. https://github.com/jaredhanson/electrolyte
  2. https://www.npmjs.com/package/node-dependency-injection
  3. https://www.npmjs.com/package/di

但他们似乎要么放弃(二),不维护,或者我们不能弄清楚(电解质)。

是否有一些标准或简单的解决scheme,许多人正在使用,最好logging在凡人和一个非“明确”的依赖的例子?

更新1

看来我用来创build我的服务的模式创build一个新的实例,它被使用/调用。 服务应该是单身人士。 简单的解决scheme是将其添加到我的服务的底部:

 let playerService = new PlayerService(); module.exports = playerService; 

显然,这只会创build对象的一个​​实例,不pipe现在多次需要(“./ playerService”)被调用。

为了保持每个env的configuration,正确的方法可能是(类似于你的build议) – 保持一个configuration/ env目录,并把每个env的文件,如development.js,test.js等,并在每个把正确的价值观。 例如:

 module.exports = { playerService: 'dev/PlayerService' } 

并要求:

 let env = process.env.NODE_ENV || 'development' , envConfig = require("./config/" + env) , playerService = require(envConfig.playerService) 

你也可以像这样在一个文件中包含全部内容:config.js:

 module.exports = { development:{ playerService: '....' }, test:{ playerService: '....' } } 

并要求:

 let env = process.env.NODE_ENV || 'development' , config = require("./config") , playerService = require(config[env][playerService]) 

这是一个常见的用例。

或者,如果每个env都有目录中的所有服务,例如dev一个目录,一个testing等目录,则不需要configuration,您可以这样要求:

  let env = process.env.NODE_ENV || 'development' , playerService = require('./' + env + '/playerServcie') 

在节点js中创build单例服务应该很简单,看看下面的内容:

https://blog.risingstack.com/fundamental-node-js-design-patterns/

https://www.sitepoint.com/javascript-design-patterns-singleton/

和这个

希望这可以帮助。