我非常震惊地发现,默认情况下,node中的"require“会创建一个单例。有人可能会假设许多人都有他们需要的模块,这些模块有状态,但被创建为单例,所以一旦有多个并发用户,就中断应用程序。
我们有相反的问题,需要创建一个非单例,而我们不知道如何解决这个问题。
因为我的大脑是java开发人员,所以我们所有的节点文件/模块都是这样定义的:
文件playerService.js
const Player = require("./player")
class PlayerService {
constructor(timeout) {
// some stuff
}
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当我们想要使用它时,我们这样做:
someHandler.js
const PlayerService = require("./playerService")
const SomeService = require("./someService")
playerService = new PlayerService(3000)
// some code which gets a player
playerService.updatePlayer(somePlayer)虽然requires()在默认情况下会创建单例,但在上面的例子中,我猜它不是在创建单例,因为每个websocket消息(在我们的例子中)都会在堆栈中调用的每个模块中实例化一个新的对象。这是一个很大的开销-为了服务一条消息,服务可能会被实例化5次,因为有5个不同的子服务/助手类相互调用,并且都做了一个requires(),然后乘以并发用户的数量,你会得到很多不必要的对象创建。
1)由于服务没有状态,我们如何修改上面的类以作为单例工作?
2)是否有全局导入或创建全局对象的概念,以便我们可以为特定的websocket连接和/或所有连接导入(也称为要求)和/或实例化一次对象?我们没有index.js或类似的。不得不为堆栈中的每个js文件重新请求依赖的模块/文件似乎很疯狂。请注意,我们研究了DI选项,但发现它们太神秘了,无法理解如何使用它们,因为我们不是js专家,尽管我们尝试了多年。
发布于 2017-06-27 22:38:16
您可以简单地在文件中创建一个实例并将其导出。
let playerService = new PlayerService();
module.exports = playerService;在这种情况下,您可能希望为用作构造函数参数的成员变量添加setter,以确保封装。
还要注意的是,由于其原型模型(more),在javascript中使用new创建对象实例比使用传统的OOP语言更便宜。
所以,当你真的需要新的实例时,不要犹豫(如你的代码中所见,你真的想共享超时构造函数参数吗?),因为javascript对象在使用prototype方法时内存效率很高,而且现代引擎有很好的垃圾回收器来防止内存泄漏。
https://stackoverflow.com/questions/44781776
复制相似问题