我只是在调用 `ìo.sockets.emit('hey', data); 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] } }
我的代码是:
`````` JAVASCRIPT
if (game.scoreTeamTwo > game.scoreTeamOne && game.scoreTeamTwo > game.scoreTeamThree && game.scoreTeamTwo > game.scoreTeamFour) {
game.winner = 2;
io.sockets.emit('CTFEnd', 游戏);
}
//它只是查看团队 1 是否赢了比赛,当它赢了时会发出CTFEnd
和所有其他游戏数据
``````
找到了我的问题的“解决方案”。 我可以发送分散的每条数据,但它不适用于对象
我最近也遇到了这个错误,唯一的区别是它只是偶尔发生在我身上。 整个上午都在测试,但我无法复制该问题。
对我来说,只有当 obj 很大时,它才无法向所有人发射。
@BenBals如果对象太大,那么一个不错的解决方法是以字符串的形式发送它,即在它上面运行JSON.stringify()
我有另一个工作,但我考虑过。
:cry: 调查这个
发出类型的对象时有同样的问题:
{success: file, content: file.content} 其中 file.content 是 Buffer 对象,file 的所有其他属性都是字符串。
必须将字段内容直接添加到对象中,因为 hasBin() 只检查对象的第一级。 但是当它尝试发送缓冲区时,它得到了“最大调用堆栈超出”
您可以通过发出套接字对象(至少是一种方式)来复制它,所以(下面是 server to -> client )
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
});
});
寻找解决方案...
对不起,但我的中文不是很好。 你能不能把这个翻译成英文。
做了谷歌翻译,结果是“找到解决方案......”......几乎不值得回应。 作为记录,解决方案是不要通过 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);”
我尝试简化“数据”对象并保持它很小,并且它起作用了。
--AND,我查看了 src 代码,发现了这个:
当您的“数据”对象具有递归属性引用时,此代码将崩溃。
例如proto > proto > proto ...
+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 ,一旦我通过 io.emit 发送了100,000 个事件,我就会看到这种情况发生。 我有 1 个连接的袜子,所以 100,000 似乎是一个硬上限。
似乎这是 Node(或 JavaScript 运行时)强加的限制,并且 Socket.io 每次调用时都会持有对某些内容的引用,因此当您点击第 100,000 次时,它就会倒下。
使用 Node 5.11.0 和 Socketio 1.4.8 进行测试。 我的 Node 版本(以及我的操作系统等,真的不知道这 100,000 来自哪里)与@shunjikonishi 不同,这可以解释为什么我达到了 100,000 的限制而他达到了 200,000。
我使用 ws.js 运行了完全相同的代码,它运行良好,超过 100,000 个套接字发出没有问题,所以可能是 Socket.io 的问题。
Socket IO 是否有可能实现防止递归数据发出并因此错误而失败的防护措施? 一个简单的检测可以防止这个错误的发生,而是发出一个更有意义的错误,比如“你可能正在尝试发送循环数据”。 这将使调试更容易。
@adamreisnz欢迎您提出 PR ;)
当有人在我发表评论 5 个月后提到我时,总是让我措手不及 😆
我也遇到了这个错误。 这就是为什么我要浪费两个小时来检查我的整个代码:<。
我认为它是由像 A={B:{C:A}} 这样的递归对象引起的,显然socket是一个递归对象。
事实上,我猜这是因为在 buffer.js 中,他们使用递归来查找您要发送的数据长度。 然后得到“超出最大调用堆栈大小”。 如果他们使用 JSON.stringify() 来获取长度,则会出现另一个关于“圆形结构”的明显错误。 顺便说一句,它对谷歌有一个不好的关键词!
我也刚碰到这个。
如果尝试发送具有循环引用的对象, hasBin
将用递归循环填充堆栈。
Shucks,我看到有一个已经开放了 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>)
最有用的评论
这可能是因为您试图发送一个带有循环引用的对象,导致递归调用超出堆栈大小。