Socket.io: RangeError: превышен максимальный размер стека вызовов

Созданный на 4 июл. 2014  ·  32Комментарии  ·  Источник: socketio/socket.io

Я просто вызываю «ìo.sockets.emit (« эй », данные); and it will crash with RangeError: Превышен максимальный размер стека вызовов . I use it in other places in my app and it works fine. I am not repeating this (checked with console). The logs say the error is in socket.io/node_modules/has-binary-data/index.js: 46 ''.

Не знаю, в чем проблема. Я пробовал регистрировать io.sockets прямо перед его использованием, и он выводит следующее:

{ name: '/',
17:39:37 web.1  |   server:
17:39:37 web.1  |    { nsps: { '/': [Circular] },
17:39:37 web.1  |      _path: '/socket.io',
17:39:37 web.1  |      _serveClient: true,
17:39:37 web.1  |      _adapter: [Function: Adapter],
17:39:37 web.1  |      _origins: '*:*',
17:39:37 web.1  |      sockets: [Circular],
17:39:37 web.1  |      eio:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      engine:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   sockets:
17:39:37 web.1  |    [ { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] },
17:39:37 web.1  |      { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] } ],
17:39:37 web.1  |   connected:
17:39:37 web.1  |    { RfgXeMgHeP_9SQC5AAAC:
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      '7TEjGJjWzxObulClAAAD':
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   fns: [],
17:39:37 web.1  |   ids: 0,
17:39:37 web.1  |   acks: {},
17:39:37 web.1  |   adapter:
17:39:37 web.1  |    { nsp: [Circular],
17:39:37 web.1  |      rooms:
17:39:37 web.1  |       { '5MGPNOdO4th_dOuZAAAA': [],
17:39:37 web.1  |         '64rUhxxp--4Qk1MqAAAB': [],
17:39:37 web.1  |         RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      sids:
17:39:37 web.1  |       { RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      encoder: {} },
17:39:37 web.1  |   _events: { connection: [Function] } }

Мой код:

ЯВАСКРИПТ

if (game.scoreTeamTwo> game.scoreTeamOne && game.scoreTeamTwo> game.scoreTeamThree && game.scoreTeamTwo> game.scoreTeamFour) {
game.winner = 2;
io.sockets.emit ('CTFEnd', игра);
}

// Просто смотрит, выиграла ли команда 1 игру, и когда она это делает, выдает CTFEnd и все остальные игровые данные
`` `` `

Самый полезный комментарий

Вероятно, это произошло из-за того, что вы пытались отправить объект с круговыми ссылками, в результате чего рекурсивные вызовы превышали размер стека.

Все 32 Комментарий

Нашел "решение" своей проблемы. Я могу отправить каждую отдельную часть данных, но он НЕ работает с объектами.

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

Для меня это было то, что он не мог излучать кому-либо, только когда объект был слишком большим.

@BenBals, если объект слишком большой, то достойный обходной путь - отправить его в виде строки, т.е. запустить на нем JSON.stringify()

У меня есть другая работа, но я обдумал это.

: cry: вглядываясь в это

имеет ту же проблему при испускании объекта типа:
{success: file, content: file.content}, где file.content - это объект буфера, а все остальные свойства файла - это строки.

пришлось добавить содержимое поля непосредственно к объектам, потому что hasBin () проверяет только первый уровень объекта. Но когда он затем попытался отправить буфер, он получил `` Превышен максимальный стек вызовов ''

Вы можете реплицировать это, испуская объект сокета (по крайней мере, в одну сторону), поэтому (ниже будет сервер -> клиент)

socket.emit('crash', {socket:socket});

Мне любопытно, есть ли у этого реальное исправление.

Есть новости по этой проблеме?
РЕДАКТИРОВАТЬ: Моя проблема заключалась в том, что я пытался отправлять рекурсивные объекты.

Интересно, что я получаю ту же ошибку при попытке передать данные Firebase клиентской стороне.

Ошибка

node_modules/socket.io/node_modules/has-binary-data/index.js:46

for (var key in obj) {
                ^
RangeError: Maximum call stack size exceeded

На стороне сервера

var DB = new Firebase('https://1234abcd.firebaseIO.com');
var USERS = DB.child("users");

io.sockets.on('connection', function(socket){

    socket.emit('test', {
        db: USERS
    });

});

Найти решение...

Извините, но мой китайский не так уж хорош. Не могли бы вы перевести это на английский?

Сделал Google Translate, и он выходит: "Найдите решение ..." ... вряд ли стоит отвечать. Для записи, решение состоит в том, чтобы не передавать такой большой объем данных через socket.io ... это сокет, который был разработан для быстрых и коротких ответов. Разбейте свой ответ или отправьте его через ajax. Отказ от подписки на эту ветку.

Одна вещь, которую вы можете сделать с помощью кода socket.io, - это просто асинхронно перебирать объект и его свойства, например:

var props = [];
var obj = { a: 1, b:2, c: { d: 3, e: 4 } };

function next_prop(callback){
  if (!props.length){
    setTimeout(callback);
    return;
  }
  var prop = props.shift();
  //do whatever with the prop, call parse_obj on it if it's an object
  setTimeout(next_prop);
}

function parse_obj(obj, callback){
  for (var i in obj){
    props.push(i);
  }
  setTimeout(function(){next_prop(callback);});
}

parse_obj(obj);

Конечно, это не настоящий код, который вы должны использовать, потому что для каждого отдельного объекта должна быть оболочка функций на случай, если они вложены, иначе у вас будут конфликты с тем, какой объект анализируется.

Я тоже получаю эту ошибку, мой код такой: "io.sockets.emit ('key', data);"
Я пытаюсь упростить объект «данные» и сделать его маленьким, и это сработало.
--И я заглянул в код src, нашел это:

image_20150306180547

когда ваш объект «данные» имеет рекурсивную ссылку на атрибут, этот код выйдет из строя.
например, прото > прото > прото ...

+1 Может ли основная команда использовать асинхронную версию двоичной проверки, я могу помочь с этой настройкой

Я могу воспроизвести проблему, отправив объект сокета :)

+1 IE11 показывает "вне стека" в _hasBinary.

Эта ошибка показалась мне, когда я пытался отправить весь объект сокета обратно клиенту. Все, что мне действительно_ нужно, это socket.id поэтому ошибка исчезла, когда я отправил обратно меньший элемент - в моем случае socket.id вместо всего объекта socket

Вероятно, это произошло из-за того, что вы пытались отправить объект с круговыми ссылками, в результате чего рекурсивные вызовы превышали размер стека.

@LordMajestros Это исправило для меня! Спасибо

@GerbenHofman пожалуйста

Я столкнулся с такой же ошибкой на NodeJS v4.4.4 и socket.io v1.4.5.

В моем случае это происходит после события отключения.
И это происходит только тогда, когда я звоню на socket.emit более 200 000 раз.

Если количество вызовов socket.emit составляет около 100 000, эта ошибка никогда не возникает.

Параметр, который я использую с emit , всегда является строкой

Эта информация вам помогает?

Чтобы добавить к @shunjikonishi , я видел, как это произошло, как только я отправил ровно 100 000 событий через io.emit. У меня подключен 1 сокет, поэтому кажется, что 100000 - это жесткий предел.

Похоже, это ограничение, наложенное Node (или средой выполнения JavaScript), и Socket.io содержит ссылку на что-то каждый раз, когда вы вызываете emit, поэтому, когда вы нажимаете 100000-й emit, он просто падает.

Протестировано с Node 5.11.0 и Socketio 1.4.8. Моя версия Node отличается (как и моя операционная система и т. Д., На самом деле не знаю, откуда взялись эти 100000), чем

Я запустил тот же самый код, используя ws.js, и он работал нормально, без проблем превысил 100000 излучаемых сокетов, так что, возможно, это проблема с Socket.io.

Есть ли шанс, что Socket IO реализует защиту от рекурсивных данных, излучаемых из и сбой с этой ошибкой? Простое обнаружение может предотвратить возникновение этой ошибки и вместо этого выдать более значимую ошибку, например «Возможно, вы пытаетесь отправить циклические данные». Это упростило бы отладку.

Есть довольно много достойных решений для обнаружения циклических данных: https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

Одно короткое решение полагается на JSON.stringify, чтобы найти проблему:

function isObjectCircular(obj) {
    try {
        JSON.stringify(circularReference);
    } catch(err) {
        return (err.toString() === 'TypeError: Converting circular structure to JSON');
    }
    return false;
}

Подробнее: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

@adamreisnz Добро пожаловать на пиар;)

Меня всегда застает врасплох, когда кто-то упоминает обо мне через 5 месяцев после того, как я оставил комментарий 😆

Я тоже встречал эту ошибку. Вот почему я трачу два часа на проверку всех кодов: <.
Я думаю, что это вызвано объектом рекурсии, таким как A = {B: {C: A}}, и, очевидно, сокет является объектом рекурсии.
На самом деле, я предполагаю, что это произошло потому, что в buffer.js они используют рекурсию для определения длины данных, которые вы хотите отправить. И затем получите «превышен максимальный размер стека вызовов». Если они используют JSON.stringify () для получения длины, будет еще одна явная ошибка, связанная с «круговой структурой». Между прочим, это плохое ключевое слово для Google!

Я тоже с этим столкнулся.

hasBin заполнит стек рекурсивным циклом при попытке отправить объект, имеющий циклическую ссылку.

Шакс, я вижу, что уже 2 года существует PR, который исправит это:

@dustingraham исправление выглядит отлично, хотя я не уверен в последствиях для производительности.

Кроме того, даже если он больше не вызывает метод hasBinary , я боюсь, что метод JSON.stringify, который вызывается позже в коде, все равно выдаст ошибку:

> var a = {};
undefined
> var b = { a: a };
undefined
> a.b = b
{ a: { b: [Circular] } }
> JSON.stringify(a)
Thrown:
TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)
Была ли эта страница полезной?
0 / 5 - 0 рейтинги