我得到以下警告:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:385:29)
    at Server.<anonymous> (server.js:20:17)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1410:22)
    at TCP.onread (net.js:354:27)

我在server.js中写了这样的代码:

http.createServer(
    function (req, res) { ... }).listen(3013);

如何解决这个问题?


当前回答

I prefer to hunt down and fix problems instead of suppressing logs whenever possible. After a couple days of observing this issue in my app, I realized I was setting listeners on the req.socket in an Express middleware to catch socket io errors that kept popping up. At some point, I learned that that was not necessary, but I kept the listeners around anyway. I just removed them and the error you are experiencing went away. I verified it was the cause by running requests to my server with and without the following middleware:

socketEventsHandler(req, res, next) {
        req.socket.on("error", function(err) {
            console.error('------REQ ERROR')
            console.error(err.stack)
        });
        res.socket.on("error", function(err) {
            console.error('------RES ERROR')
            console.error(err.stack)
        });
        next();
    }

删除该中间件将停止您所看到的警告。我会查看您的代码,并尝试找到您可能设置了不需要的侦听器的任何地方。

其他回答

我想在这里指出,这个警告是有原因的,正确的解决方法很可能不是增加限制,而是弄清楚为什么要向同一个事件添加如此多的侦听器。只有当您知道为什么要添加这么多侦听器并且确信这是您真正想要的时候,才增加限制。

我找到了这个页面,因为我得到了这个警告,在我的情况下,我正在使用的一些代码中有一个错误,将全局对象转换为EventEmitter!我当然不建议在全球范围内增加限制,因为你不想让这些事情被忽视。

You said you are using process.on('uncaughtException', callback); Where are you executing this statement? Is it within the callback passed to http.createServer?If yes, different copy of the same callback will get attached to the uncaughtException event upon each new request, because the function (req, res) { ... } gets executed everytime a new request comes in and so will the statement process.on('uncaughtException', callback);Note that the process object is global to all your requests and adding listeners to its event everytime a new request comes in will not make any sense. You might not want such kind of behaviour. In case you want to attach a new listener for each new request, you should remove all previous listeners attached to the event as they no longer would be required using: process.removeAllListeners('uncaughtException');

感谢RLaaa给了我一个如何解决警告的真正问题/根本原因的想法。在我的例子中,是MySQL有bug的代码。

假设你写了一个承诺,里面的代码是这样的:

pool.getConnection((err, conn) => {

  if(err) reject(err)

  const q = 'SELECT * from `a_table`'

  conn.query(q, [], (err, rows) => {

    conn.release()

    if(err) reject(err)

    // do something
  })

  conn.on('error', (err) => {

     reject(err)
  })
})

注意,代码中有一个conn.on('error')侦听器。代码一遍又一遍地添加监听器取决于调用查询的次数。 同时if(err) reject(err)做同样的事情。

所以我删除了conn.on('error')监听器,瞧…解决了! 希望这对你有所帮助。

我们团队对此的解决方案是从.npmrc中删除注册表路径。rc文件中有两个路径别名,其中一个指向已弃用的Artifactory实例。

这个错误与我们的应用程序的实际代码无关,而是与我们的开发环境有关。

I prefer to hunt down and fix problems instead of suppressing logs whenever possible. After a couple days of observing this issue in my app, I realized I was setting listeners on the req.socket in an Express middleware to catch socket io errors that kept popping up. At some point, I learned that that was not necessary, but I kept the listeners around anyway. I just removed them and the error you are experiencing went away. I verified it was the cause by running requests to my server with and without the following middleware:

socketEventsHandler(req, res, next) {
        req.socket.on("error", function(err) {
            console.error('------REQ ERROR')
            console.error(err.stack)
        });
        res.socket.on("error", function(err) {
            console.error('------RES ERROR')
            console.error(err.stack)
        });
        next();
    }

删除该中间件将停止您所看到的警告。我会查看您的代码,并尝试找到您可能设置了不需要的侦听器的任何地方。