Socket.io: RangeError: Maximale Call-Stack-Größe überschritten

Erstellt am 4. Juli 2014  ·  32Kommentare  ·  Quelle: socketio/socket.io

Ich rufe nur `ìo.sockets.emit('hey', data); and it will crash with RangeError: Maximale Call-Stack-Größe überschritten . 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``.

Ich weiß nicht wo das Problem liegt. Ich habe versucht, io.sockets direkt vor der Verwendung zu protokollieren und es gibt Folgendes aus:

{ 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] } }

Mein Code ist:

`````` JAVASCRIPT

if (game.scoreTeamTwo > game.scoreTeamOne && game.scoreTeamTwo > game.scoreTeamThree && game.scoreTeamTwo > game.scoreTeamFour) {
Spiel.Gewinner = 2;
io.sockets.emit('CTFEnd', Spiel);
}

//Es schaut nur, ob Team 1 das Spiel gewonnen hat und wenn es das tut, gibt es CTFEnd und alle anderen Spieldaten aus
``````

Hilfreichster Kommentar

Dies geschah wahrscheinlich, weil Sie versuchten, ein Objekt mit Zirkelverweisen zu senden, was zu rekursiven Aufrufen führte, die die Stapelgröße überschritten.

Alle 32 Kommentare

Habe eine "Lösung" für mein Problem gefunden. Ich kann jedes einzelne Stück Daten getrennt senden, aber es funktioniert NICHT mit Objekten

Ich habe diesen Fehler vor kurzem auch bekommen, der einzige Unterschied ist, dass er nur gelegentlich bei mir auftritt. Habe den ganzen Morgen getestet und konnte das Problem nicht reproduzieren.

Für mich war es so, dass es nur dann nicht zu jedem strahlen konnte, wenn das Obj zu groß war.

@BenBals Wenn das Objekt zu groß ist, besteht eine anständige Problemumgehung darin, es in Form einer Zeichenfolge zu senden, dh JSON.stringify() darauf auszuführen

Ich habe eine andere Arbeit herum, aber ich habe das in Betracht gezogen.

:weinen: schau dir das an

hat das gleiche Problem beim Ausgeben eines Objekts des Typs:
{Erfolg: Datei, Inhalt: Datei.Inhalt} wobei Datei.Inhalt das Pufferobjekt ist und alle anderen Eigenschaften von Datei Zeichenfolgen sind.

musste den Feldinhalt direkt zu den Objekten hinzufügen, da hasBin() nur die erste Ebene eines Objekts überprüft. Aber als es dann versuchte, den Puffer zu senden, wurde 'Maximaler Aufrufstapel überschritten'

Sie können dies replizieren, indem Sie das Socket-Objekt (mindestens in eine Richtung) ausgeben (unten wäre Server zu -> Client).

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

Ich bin gespannt, ob es eine tatsächliche Lösung gibt.

Irgendein Update zu diesem Thema?
BEARBEITEN: Mein Problem war, dass ich versuchte, rekursive Objekte zu senden.

Interessanterweise erhalte ich denselben Fehler, wenn ich versuche, meine Firebase-Daten an die Clientseite zu übergeben.

Fehler

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

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

Serverseitig

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

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

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

});

Finde eine Lösung...

Tut mir leid, aber mein Chinesisch ist nicht so toll. Wären Sie so nett, dies ins Englische zu übersetzen.

Habe einen Google-Übersetzer gemacht und es kommt heraus, dass "Find the Solution..." ... kaum wert ist, darauf zu antworten. Um es festzuhalten, die Lösung besteht darin, nicht so große Datenmengen über socket.io zu übergeben ... es ist ein Socket, der für schnelle, kurze Antworten entwickelt wurde. Brechen Sie Ihre Antwort auf oder senden Sie sie über Ajax. Abmelden dieses Threads.

Eine Sache, die Sie mit dem socket.io-Code tun können, ist, das Objekt und seine Eigenschaften einfach asynchron zu iterieren, etwa:

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

Natürlich ist dies nicht der eigentliche Code, den Sie verwenden sollten, da für jedes einzelne Objekt Funktionen umschlossen werden müssen, falls sie verschachtelt sind. Andernfalls treten Konflikte mit dem analysierten Objekt auf.

Ich bekomme auch nur diesen Fehler, mein Code lautet wie folgt: "io.sockets.emit('key', data);"
Ich versuche, das Objekt "Daten" zu vereinfachen und klein zu halten, und es hat funktioniert.
--UND, ich schaue in den src-Code und habe dies gefunden:

image_20150306180547

Wenn Ihr "Daten"-Objekt über rekursive Attributverweise verfügt, würde dieser Code abstürzen.
zB proto > proto > proto ...

+1 würde das Kernteam eine asynchrone Version der Binärüberprüfung wünschen, kann ich helfen, dieses Setup zu erhalten

Ich kann das Problem reproduzieren, indem ich das Socket-Objekt sende :)

+1 IE11 zeigt in _hasBinary 'nicht genügend Stapelspeicher' an.

Dieser Fehler wurde bei mir angezeigt, als ich versuchte, das gesamte Socket-Objekt an den Client zurückzusenden. Alles, was ich _wirklich_ brauchte, war socket.id also verschwand der Fehler, als ich einen kleineren Artikel zurückschickte – in meinem Fall socket.id anstelle des gesamten socket Objekts

Dies geschah wahrscheinlich, weil Sie versuchten, ein Objekt mit Zirkelverweisen zu senden, was zu rekursiven Aufrufen führte, die die Stapelgröße überschritten.

@LordMajestros Das hat es für mich behoben! Vielen Dank

@GerbenHofman gern

Ich hatte den gleichen Fehler bei NodeJS v4.4.4 und socket.io v1.4.5.

In meinem Fall passiert es nach dem Trennereignis.
Und es passiert nur, wenn ich socket.emit mehr als 200.000 Mal angerufen habe.

Wenn die Anzahl der Anrufe socket.emit ungefähr 100.000 beträgt, tritt dieser Fehler nie auf.

Der Parameter, den ich mit emit ist immer string

Helfen Ihnen diese Informationen?

Nur um @shunjikonishi hinzuzufügen, ich habe dies gesehen, sobald ich genau 100.000 Ereignisse über io.emit gesendet habe. Ich habe 1 angeschlossene Socke, also scheint 100.000 eine feste Obergrenze zu sein.

Scheint, als wäre dies ein von Node (oder der JavaScript-Laufzeit) auferlegtes Limit, und Socket.io hält jedes Mal, wenn Sie emit aufrufen, einen Verweis auf etwas, sodass es beim Erreichen des 100.000sten Emits einfach umfällt.

Getestet mit Node 5.11.0 und Socketio 1.4.8. Meine Version von Node ist anders (sowie mein Betriebssystem usw., wirklich keine Ahnung, woher diese 100.000 kommen) als @shunjikonishi, was erklären könnte, warum ich das Limit bei 100.000 erreicht habe, während er auf 200.000 kam.

Ich habe genau den gleichen Code mit ws.js ausgeführt und er hat gut funktioniert, überstieg problemlos 100.000 Socket-Emissionen, also ist es vielleicht ein Problem mit Socket.io.

Besteht die Möglichkeit, dass Socket IO einen Schutz gegen rekursive Daten implementiert, die von diesem Fehler ausgegeben werden und mit diesem fehlschlagen? Eine einfache Erkennung könnte diesen Fehler verhindern und stattdessen einen aussagekräftigeren Fehler ausgeben, z. B. "Sie versuchen möglicherweise, kreisförmige Daten zu senden". Das würde das Debuggen erleichtern.

Es gibt einige anständige Lösungen zum Erkennen von zirkulären Daten: https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

Eine kurze Lösung basiert auf JSON.stringify, um das Problem zu finden:

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

Weitere Details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

@adamreisnz Du

Es überrascht mich immer, wenn mich jemand 5 Monate nach meinem Kommentar erwähnt

Ich bin auch auf diesen Fehler gestoßen. Und deshalb verschwende ich zwei Stunden damit, meine ganzen Codes zu überprüfen :<.
Ich denke, es wird durch ein Rekursionsobjekt wie A = {B: {C: A}} verursacht, und offensichtlich ist Socket ein Rekursionsobjekt.
Ich denke, es ist tatsächlich passiert, weil in buffer.js eine Rekursion verwendet wird, um die Länge der Daten zu ermitteln, die Sie senden möchten. Und dann die "maximale Aufrufstapelgröße überschritten" erhalten. Wenn sie JSON.stringify() verwenden, um die Länge zu erhalten, gibt es einen weiteren eindeutigen Fehler bezüglich "Kreisstruktur". Übrigens hat es ein schlechtes Stichwort zum Googlen!

Ich bin auch gerade darauf gestoßen.

hasBin füllt den Stack mit einer rekursiven Schleife, wenn versucht wird, ein Objekt mit einer zirkulären Referenz zu senden.

Mist, ich sehe, es gibt eine seit 2 Jahren geöffnete PR, die das beheben würde:

@dustingraham Der Fix sieht gut aus, obwohl ich mir über die Auswirkungen auf die Leistung nicht sicher bin.

Auch wenn die Methode hasBinary nicht mehr ausgegeben wird, befürchte ich, dass die später im Code aufgerufene Methode JSON.stringify immer noch einen Fehler ausgibt:

> 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>)
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen