Socket.io: RangeError: Ukuran tumpukan panggilan maksimum terlampaui

Dibuat pada 4 Jul 2014  ·  32Komentar  ·  Sumber: socketio/socket.io

Saya hanya memanggil `ìo.sockets.emit('hey', data); and it will crash with RangeError: Ukuran tumpukan panggilan maksimum melebihi . 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``.

Saya tidak tahu di mana masalahnya. Saya mencoba masuk io.sockets tepat sebelum menggunakannya dan menghasilkan ini:

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

Kode saya adalah:

`````` JAVASCRIPT

if (game.scoreTeamTwo > game.scoreTeamOne && game.scoreTeamTwo > game.scoreTeamTwo && game.scoreTeamTwo > game.scoreTeamFour) {
permainan.pemenang = 2;
io.sockets.emit('CTFend', permainan);
}

//Ini hanya melihat apakah tim 1 memenangkan permainan dan ketika menang mengeluarkan CTFEnd dan semua data permainan lainnya
``````

Komentar yang paling membantu

Ini mungkin terjadi karena Anda mencoba mengirim objek dengan referensi melingkar yang menghasilkan panggilan rekursif yang melebihi ukuran tumpukan.

Semua 32 komentar

Menemukan "solusi" untuk masalah saya. Saya dapat mengirim setiap bagian data yang dipisahkan, tetapi TIDAK bekerja dengan objek

Saya baru-baru ini juga mendapatkan kesalahan itu, satu-satunya perbedaan adalah bahwa itu hanya kadang-kadang terjadi pada saya. Telah menguji sepanjang pagi dan saya belum dapat mereplikasi masalahnya.

Bagi saya itu hanya tidak bisa dipancarkan ke semua orang, ketika objeknya terlalu besar.

@BenBals jika objek terlalu besar, maka solusi yang layak adalah mengirimkannya dalam bentuk string yaitu jalankan JSON.stringify() di atasnya

Saya mendapat pekerjaan lain, tetapi saya mempertimbangkannya.

:menangis: melihat ke dalam ini

memiliki masalah yang sama saat memancarkan objek bertipe:
{success: file, content: file.content} di mana file.content adalah objek Buffer, dan semua properti file lainnya adalah string.

harus menambahkan konten bidang langsung ke objek karena hasBin() hanya memeriksa tingkat pertama objek. Tetapi ketika mencoba mengirim buffer, ia mendapat 'Stack panggilan maksimum terlampaui'

Anda dapat mereplikasi ini dengan memancarkan objek soket (setidaknya satu arah) jadi (Di bawah ini adalah server ke -> client )

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

Saya ingin tahu apakah ini memiliki perbaikan yang sebenarnya.

Setiap pembaruan tentang masalah itu?
EDIT: Masalah saya adalah saya mencoba mengirim objek rekursif.

Yang cukup menarik, saya mendapatkan kesalahan yang sama ketika mencoba meneruskan data Firebase saya ke sisi klien.

Kesalahan

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

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

Sisi server

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

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

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

});

Mencari solusi...

Maaf, tapi bahasa Cina saya tidak terlalu bagus. Maukah Anda berbaik hati menerjemahkan ini ke dalam bahasa Inggris.

Apakah Google Terjemahan & keluar untuk "Temukan Solusi..." ... hampir tidak layak untuk ditanggapi. Sebagai catatan, solusinya adalah tidak melewatkan data dalam jumlah besar melalui socket.io ... ini adalah soket yang dirancang untuk respons cepat dan singkat. Pisahkan tanggapan Anda atau kirimkan melalui ajax. Berhenti berlangganan utas ini.

Satu hal yang dapat Anda lakukan dengan kode socket.io adalah secara asinkron mengulangi objek dan propertinya, seperti:

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

Tentu saja, ini bukan kode aktual yang harus Anda gunakan, karena perlu ada pembungkusan fungsi untuk setiap objek individu jika mereka bersarang, jika tidak, Anda akan memiliki konflik dengan objek apa yang sedang diuraikan.

Saya baru saja mendapatkan kesalahan itu juga, kode saya seperti: "io.sockets.emit('key', data);"
saya mencoba menyederhanakan objek "data" dan membuatnya tetap kecil, dan itu berhasil.
--DAN, saya melihat ke dalam kode src, menemukan ini:

image_20150306180547

ketika objek "data" Anda memiliki referensi atribut rekursif, kode ini akan macet.
misalnya proto > proto > proto ...

+1 apakah tim inti akan menyukai versi async dari pemeriksaan biner saya dapat membantu mendapatkan pengaturan itu?

Saya dapat mereproduksi masalah dengan mengirimkan objek socket :)

+1 IE11 menunjukkan 'kehabisan ruang tumpukan' di _hasBinary.

Kesalahan ini muncul untuk saya ketika saya mencoba mengirim seluruh objek soket kembali ke klien. Yang saya _benar-benar_ butuhkan hanyalah socket.id sehingga kesalahan hilang ketika saya mengirim kembali item yang lebih kecil — dalam kasus saya, socket.id alih-alih seluruh objek socket

Ini mungkin terjadi karena Anda mencoba mengirim objek dengan referensi melingkar yang menghasilkan panggilan rekursif yang melebihi ukuran tumpukan.

@LordMajestros Itu memperbaikinya untuk saya! Terima kasih

@GerbenHofman sama- sama

Saya menghadapi kesalahan yang sama pada NodeJS v4.4.4 dan socket.io v1.4.5.

Dalam kasus saya, itu terjadi setelah acara disconnect.
Dan itu terjadi hanya ketika saya menelepon socket.emit lebih dari 200.000 kali.

Jika jumlah panggilan socket.emit sekitar 100.000, kesalahan ini tidak pernah terjadi.

Parameter yang saya gunakan dengan emit selalu string

Apakah informasi ini membantu Anda?

Hanya untuk menambahkan ke @shunjikonishi , saya telah melihat ini terjadi segera setelah saya mengirim tepat 100.000 acara melalui io.emit. Saya memiliki 1 socked yang terhubung, jadi sepertinya 100.000 adalah hard cap.

Sepertinya ini adalah batas yang diberlakukan oleh Node (atau runtime JavaScript) dan Socket.io memegang referensi ke sesuatu setiap kali Anda memanggil emit, jadi ketika Anda mencapai emisi ke 100.000, itu jatuh begitu saja.

Diuji dengan Node 5.11.0 dan Socketio 1.4.8. Versi Node saya berbeda (juga sistem operasi saya dll, benar-benar tidak tahu dari mana 100.000 ini berasal) dari @shunjikonishi yang mungkin menjelaskan mengapa saya mencapai batas 100.000 sedangkan dia mendapatkan hingga 200.000.

Saya menjalankan kode yang sama persis menggunakan ws.js dan berfungsi dengan baik, melampaui 100.000 soket yang dipancarkan tanpa masalah, jadi mungkin ini masalah dengan Socket.io.

Apakah ada kemungkinan Socket IO menerapkan pelindung terhadap data rekursif yang dipancarkan dan gagal dengan kesalahan ini? Deteksi sederhana dapat mencegah kesalahan ini terjadi dan malah memancarkan kesalahan yang lebih bermakna, seperti "Anda mungkin mencoba mengirim data melingkar". Itu akan membuatnya lebih mudah untuk di-debug.

Ada beberapa solusi yang layak untuk mendeteksi data melingkar: https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

Satu solusi singkat bergantung pada JSON.stringify untuk menemukan masalah:

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

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

@adamreisnz Anda dipersilakan untuk membuat PR ;)

Itu selalu membuat saya lengah ketika seseorang menyebut saya 5 bulan setelah saya berkomentar

Saya bertemu kesalahan ini juga. Dan itulah mengapa saya membuang waktu dua jam untuk memeriksa seluruh kode saya :<.
Saya pikir itu disebabkan oleh objek rekursi seperti A={B:{C:A}}, dan jelas socket adalah objek rekursi.
Bahkan, saya kira itu terjadi karena di buffer.js, mereka menggunakan rekursi untuk menemukan panjang data yang ingin Anda kirim. Dan kemudian dapatkan "ukuran tumpukan panggilan maksimum terlampaui". Jika mereka menggunakan JSON.stringify() untuk mendapatkan panjangnya, akan ada kesalahan lain yang jelas tentang "struktur melingkar". Omong-omong, ini memiliki kata kunci yang buruk untuk google!

Saya baru saja mengalami ini juga.

hasBin akan mengisi tumpukan dengan loop rekursif jika mencoba mengirim objek yang memiliki referensi melingkar.

Astaga, saya melihat ada PR yang telah terbuka selama 2 tahun yang akan memperbaikinya:

@dustingraham perbaikannya terlihat bagus, meskipun saya tidak yakin tentang implikasi kinerjanya.

Juga, bahkan jika itu tidak memasukkan metode hasBinary lagi, saya khawatir metode JSON.stringify yang dipanggil nanti dalam kode masih akan menimbulkan kesalahan:

> 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>)
Apakah halaman ini membantu?
0 / 5 - 0 peringkat