обнаружена утечка памяти в EventEmitter - PullRequest
177 голосов
/ 19 марта 2012

Я получаю следующее предупреждение:

(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);

Как это исправить?

Ответы [ 16 ]

158 голосов
/ 16 июля 2015

Я хотел бы указать здесь, что это предупреждение есть по причине, и есть хороший шанс, что правильное исправление - не , увеличивающее ограничение, но выясняющее, почему вы добавляете так много слушателей кто же событие.Увеличивайте лимит только в том случае, если вы знаете, почему добавляется так много слушателей, и уверены, что это именно то, что вам действительно нужно.

Я нашел эту страницу, потому что получил это предупреждение, и в моем случае в каком-то коде была ошибка.использовал это превращало глобальный объект в EventEmitter!Я бы, конечно, посоветовал не увеличивать лимит в глобальном масштабе, потому что вы не хотите, чтобы эти вещи остались незамеченными.

82 голосов
/ 19 марта 2012

Это объясняется в руководстве: http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n

Какая версия Node это?Какой другой код у вас есть?Это не нормальное поведение.

Короче говоря, его: process.setMaxListeners(0);

Также см .: node.js - запрос - Как сделать «emitter.setMaxListeners ()»?1010 *

73 голосов
/ 03 октября 2014

По умолчанию для любого отдельного события можно зарегистрировать максимум 10 слушателей.

Если это ваш код, вы можете указать maxListeners через:

const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)

Но если это не ваш код, вы можете использовать хитрость, чтобы увеличить ограничение по умолчанию в глобальном масштабе:

require('events').EventEmitter.prototype._maxListeners = 100;

Конечно, вы можете отключить ограничения, но будьте осторожны:

// turn off limits by default (BE CAREFUL)
require('events').EventEmitter.prototype._maxListeners = 0;

КСТАТИ. Код должен быть в самом начале приложения.

ADD: начиная с узла 0.11, этот код также работает для изменения предела по умолчанию:

require('events').EventEmitter.defaultMaxListeners = 0
53 голосов
/ 09 июня 2017

Принятый ответ предоставляет семантику о том, как увеличить лимит, но, как @voltrevo указал, что есть предупреждение по причине, и ваш код, вероятно, содержит ошибку.

Рассмотрим следующий код ошибки:

//Assume Logger is a module that emits errors
var Logger = require('./Logger.js');

for (var i = 0; i < 11; i++) {
    //BUG: This will cause the warning
    //As the event listener is added in a loop
    Logger.on('error', function (err) {
        console.log('error writing log: ' + err)
    });

    Logger.writeLog('Hello');
}

Теперь рассмотрим правильный способ добавления слушателя:

//Good: event listener is not in a loop
Logger.on('error', function (err) {
    console.log('error writing log: ' + err)
});

for (var i = 0; i < 11; i++) {
    Logger.writeLog('Hello');
}

Поиск похожих проблем в вашем коде перед изменением maxListeners (что объясняется в других ответах)

18 голосов
/ 17 декабря 2013

Заменить .on() на once().Использование once() удаляет прослушиватели событий, когда событие обрабатывается той же функцией.Источник: http://nodeguide.com/beginner.html#using-eventemitters

Если это не помогло, переустановите restler с этим в вашем package.json "restler": "git: //github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

Это связано с неправильным поведением рестлера 0.10 с узлом.вы можете увидеть проблему закрытой на git здесь: https://github.com/danwrong/restler/issues/112 Однако npm еще не обновил это, поэтому вам следует обратиться к главе git.

3 голосов
/ 28 сентября 2016

Я также получаю это предупреждение при установке aglio на мой Mac OSX.

Я использую cmd, чтобы исправить это.

sudo npm install -g npm@next

https://github.com/npm/npm/issues/13806

1 голос
/ 13 мая 2018

Я предпочитаю выслеживать и исправлять проблемы, а не подавлять журналы всякий раз, когда это возможно.После пары дней наблюдения за этой проблемой в моем приложении я понял, что настраиваю прослушиватели на req.socket в промежуточном программном обеспечении Express, чтобы перехватывать ошибки сокета io, которые продолжали появляться.В какой-то момент я узнал, что в этом нет необходимости, но я все равно держал слушателей.Я просто удалил их, и ошибка, с которой вы столкнулись, ушла.Я подтвердил, что это было причиной, запустив запросы к моему серверу со следующим промежуточным программным обеспечением и без него:

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();
    }

Удаление этого промежуточного программного обеспечения остановило предупреждение, которое вы видите.Я бы посмотрел вокруг вашего кода и попытался найти то, где вы, возможно, настраиваете слушателей, которые вам не нужны.

1 голос
/ 11 мая 2017

У меня было это до сегодняшнего дня, когда я начинаю grunt watch. Окончательно решено

watch: {
  options: {
    maxListeners: 99,
    livereload: true
  },
}

Раздражающее сообщение пропало.

1 голос
/ 21 января 2017

Иногда эти предупреждения появляются, когда это не то, что мы сделали, а то, что мы забыли сделать!

Я сталкивался с этим предупреждением, когда устанавливал пакет dotenv с помощью npm, но раньше его прерывали.Я нашел способ добавить оператор require ('dotenv'). Load () в начале моего приложения.Вернувшись в проект, я начал получать предупреждения «Возможная утечка памяти EventEmitter».

Я предполагал, что проблема в том, что я сделал, а не в том, что я не сделал!

Как только я обнаружил свой контроль и добавил оператор require, предупреждение об утечке памяти исчезло.

1 голос
/ 22 ноября 2016

В моем случае это был child.stderr.pipe(process.stderr), который вызывался, когда я инициировал 10 (или около того) случаев ребенка.Поэтому все, что приводит к присоединению обработчика событий к тому же объекту EventEmitter в LOOP, заставляет nodejs выдавать эту ошибку.

...