是什么导致了Node.js EventEmitter警告?

xcitsw88  于 2022-09-21  发布在  Node.js
关注(0)|答案(1)|浏览(135)

我的node.js后端有很多mongoose.connection.useDb行,因为它经常需要切换数据库。今天我重新启动了服务器,收到了这样的警告:

MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connected listeners added to [NativeConnection].

我花了一些时间才找到解决方案,我发现只需添加mongoose.connection.removeAllListeners(),警告就会消失。这是什么意思,event到底是什么?感觉就像我删除了所有侦听器,使用这些数据库的代码(比如当我需要为模式创建模型时)应该不再工作,但事实并非如此。

o2g1uqev

o2g1uqev1#

这是什么意思?

此警告表示您正在为同一事件注册11个或更多侦听程序,或者调用了一些在内部导致此情况发生的代码。该警告是因为事件发射器的正常使用很少需要同一事件的11个侦听器。

相反,同一事件的这么多侦听器通常表示您在一遍又一遍地注册同一事件,或者反复调用某个函数,从而一遍又一遍地调用同一个侦听器。在您的特定情况下,您可能应该在调用.useDb()时使用noListener: true选项。请参阅此处的文档和这个troubleshooting report

如果不删除您不再使用的侦听器,可能会造成内存泄漏(正如错误消息所示),因为NodeJS无法判断您不再打算使用该侦听器。它仍然为事件注册,事件仍然可以发生,因此监听程序(您不再打算使用的监听程序)仍然处于活动状态。这会占用EventEmitter对象中的额外内存,并且(可能更重要的),它可能会阻止某些闭包变量在侦听器回调函数/作用域中得到垃圾回收。

因此,只要EventEmitter对象获得同一事件的第11个或更多侦听器,它就会发出此警告。

如果您显示了发生此警告的实际代码和上下文,我们可以给您更具体的建议,告诉您应该/不应该在该代码中执行哪些操作。以上是一般性的描述/建议,因为您没有显示您的特定代码和上下文。
什么是活动?

此警告来自EventEmitter对象,根据您的解释,每当您调用.useDb()时,该对象很可能正在数据库内部使用。您对数据库所做的某些操作会导致它为EventEmitter对象上的事件注册一个侦听器。如果您想更多地了解EventEmitter对象上下文中的事件,我建议您阅读eventEmitter documentation

简而言之,EventEmitter对象允许用户通过调用obj.addListener("someEventName", fn)或相同(但更短)的obj.on("someEventName, fn)来侦听事件,其中objEventEmitter类的示例。然后,其他代码可以触发事件obj.emit("someEventName", someData)。当事件被触发时,将调用该特定事件名称的所有注册侦听器的回调。NodeJS在其库中的许多地方使用了类似的事件对象和侦听器。例如,流使用侦听器来侦听传入数据,如stream.on('data', myCallback)中所示。

相关问题