【发布时间】:2017-11-29 22:46:50
【问题描述】:
在节点中,模块导入(又名 require())被硬编码在每个需要导入的文件(又名模块)中。这可能是数十个,在我们的例子中可能是数百个重复导入。我们以动态方式“需要”的主要是服务,例如"playerService" 具有查找、更新、获取方法等,但也可以是域对象或持久性库
关键是我们有这个“playerService”js 文件的 3 个版本。一种在本地(在内存中)为开发做所有事情,一种用本地数据库做所有事情(测试),另一种通过 API 用外部系统做所有事情(实时)。在这种情况下,开关处于开启环境(开发、测试或实时)。
值得注意的是,我们尽可能使用类,因为我们发现返回函数等函数的函数是不可读/可维护的(我们是真正为 js 苦苦挣扎的 Java 开发人员)
我们还在我们的节点应用程序中专门使用 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 的依赖注入,但还没有发现任何关于 node.js 的可理解的(见下文)。不幸的是,我们既不是 javascript 也不是节点专家,尽管我们阅读了大量内容。
目前我们正在考虑以下选项之一,但希望听到任何更好的建议:
选项 1:
- “开发”需要的硬代码,例如要求(“./dev/playerSerice”)
- 让 jenkins 构建服务器将每个文件中的源代码重写为 require("./test/playerSerice")。
选项 2:
- “开发”需要的硬代码,例如要求(“./playerSerice”)
- 让 jenkins 构建服务器将文件 /test/playerService/playerService" 交换为 ./playerService。
显然,这使得开发人员很难在不破解源代码的情况下在本地机器上运行测试版或专业版。
选项 3: 1. 将所需的模块路径放在一个配置文件中。 2. 只换掉配置文件。例如
let Config = require("./config")
let PlayerService = require(Config.playerService)
我们试图让它依赖于 env 并有一个全局配置,开发、测试和 prod 配置可以覆盖这些配置,但还没有找到一种优雅的方式来做到这一点。一种方法可能是在每个模块的顶部复制此代码:
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
选项 4: 也许这样的事情会起作用:
let env = process.env.NODE_ENV || 'development'
require("./" + env + "/playerService")
上述所有解决方案都缺乏单例 - 服务是无状态的。我们猜测节点将为每个请求(或在我们的例子中的 Web 套接字消息)构建每个服务的新副本。有没有办法减少这种情况?
显然,一些简单、可读且官方维护的依赖注入形式会很不错,可以通过某种方式在注入的类集之间切换。
我们已阅读以下帖子:
- https://blog.risingstack.com/dependency-injection-in-node-js/ 结果代码是不可读的(至少对我们来说)。如此人为的示例并没有帮助,团队只是围绕用户的某种代理包装器,而不是服务或任何有用的东西。什么是选项?为什么选择?
- https://medium.com/@Jeffijoe/dependency-injection-in-node-js-2016-edition-f2a88efdd427
但发现它们难以理解。例如。这些示例的关键字来自无中生有 - 它们似乎不是 javascript 或节点命令,并且在它们来自的文档中没有解释。
并查看了这些项目:
- https://github.com/jaredhanson/electrolyte
- https://www.npmjs.com/package/node-dependency-injection
- https://www.npmjs.com/package/di
但它们似乎要么被遗弃(di),要么没有维护,或者我们无法弄清楚(电解质)。
是否有许多人正在使用的标准或简单的 di 解决方案,理想情况下为凡人记录并带有非“表达”依赖的示例?
更新 1
似乎我用来创建服务的模式在使用/调用它时创建了一个新实例。服务应该是单例的。简单的解决方案是将其添加到我的服务底部:
let playerService = new PlayerService();
module.exports = playerService;
显然,这只会创建对象的一个实例,无论现在多次调用 require("./playerService")。
【问题讨论】:
标签: node.js dependencies