Node.js + Socket.io 超出最大调用堆栈大小
Posted
技术标签:
【中文标题】Node.js + Socket.io 超出最大调用堆栈大小【英文标题】:Node.js + Socket.io Maximum call stack size exceeded 【发布时间】:2015-02-07 04:51:10 【问题描述】:对于我的 Node 应用程序,我有一个在 Debian 上运行的服务器 (app.js),它使用 socket.io 为我的客户端 (index.html) 提供 html 和 websocket 数据。我正在尝试制作一款基于回合制的 HTML5 多人游戏。
在使用 socket.emit()/io.emit() 和 socket.on() 执行多次成功的数据传输后,我的服务器在 socket.emit() 调用时崩溃并出现错误 “事件.js:72 投掷者; //未处理的“错误”事件 RangeError:超出最大调用堆栈大小”。 我有很多 socket.on() 事件侦听器,每个侦听器都处理游戏中的不同功能(例如 roll_dice、end_turn、ready_to_play 等)。
我试图研究这个问题(发现很多关于异步循环的讨论),但无法找到如何将解决方案应用于我自己的代码。我在这里附上了相关来源。你也可以在我的 github 上查看所有源代码:https://github.com/sjmoon0/gameofdeath
index.html
var socket = io.connect('http://131.178.15.173','forceNew':true);
...
//----------------Initialization and Menu functions-----------
socket.on('load', function (data)
console.log(data);
clientID=data;
socket.emit('check_game_started', un: clientID );
socket.on('last_client_loaded', function(hasStarted)
console.log("Has game started? :"+hasStarted);
if(hasStarted==true)
$('#choosecharacter').show();
);
);
socket.on('client_disconnect', function (data)
console.log(data);
);
socket.on('client_counter', function (data)
if(data<5)
console.log(data);
incrementLoadBar(data);
allowedInGame=true;
if(!allowedInGame)
...
);
socket.on('game_started', function (data)
console.log(data);
$('#welcome').hide();
$('#choosecharacter').show();
);
socket.on('set_user', function(characterName)
chosenCharacter=characterName;
);
socket.on('disable_player_choice', function(data)
var id=data.stuff[0].chara;
incrementLoadBar(data.stuff[0].numChar);
console.log(id +" was chosen");
$('#'+id).hide();
);
//-------------------Gameplay functions
socket.on('start_gameplay',function(nonsense)
showChanges(nonsense);
$('#wait').hide();
$('#gamespace').show();
draw_c();
socket.emit('ready_to_play',chosenCharacter);
);
socket.on('take_turn',function(updatedBoard)
showChanges(updatedBoard);
if(updatedBoard.currPlayer==chosenCharacter)
promptUser(updatedBoard);
);
socket.on('roll_result',function(rollResult)
promptUser(rollResult);
);
...
$('#rollDiceButton').click(function()
socket.emit('roll_dice',chosenCharacter);
);
$('#okCloseButton').click(function()
socket.emit('end_turn',chosenCharacter);
);
$('.thumbnail').click(function(something)
socket.emit('player_chosen', something.target.id);
...
);
app.js
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
var url = require('url');
...
app.listen(8001);
function handler (req, res)
...
console.log("~Server Running~");
io.on('connection', function (socket)
console.log("A Client connected");
...
socket.emit('load', user: uID );
io.emit('client_counter',numClients);
if(numClients==4)
gameStarted=true;
console.log("Game started!");
io.emit('game_started',"The Game has begun!");
else if(numClients>4)
numClients--;
delete allClients[allClients.indexOf(socket)];
socket.on('check_game_started', function (data)
socket.emit('last_client_loaded', gameStarted);
console.log(data);
if(gameStarted)
console.log("Last Player Loaded!");
);
socket.on('player_chosen', function(cp)
...
socket.emit('set_user', cp);
...
io.emit('disable_player_choice','stuff':['chara':cp,'numChar':numCharChosen]);
if(numCharChosen==4)
io.emit('start_gameplay', boardUpdate);
);
socket.on('disconnect',function()
console.log("A client disconnected");
numClients--;
delete allClients[allClients.indexOf(socket)];
io.emit('client_disconnect',"We've lost another comrade!");
);
socket.on('ready_to_play',function(characterThatIsReadyToPlay)
io.emit('take_turn',boardUpdate);
);
socket.on('roll_dice', function(characterThatRolledDice)
var temp=generateRollResult(characterThatRolledDice)
socket.emit('roll_result',temp);
);
socket.on('end_turn',function(characterThatEndedTurn)
io.emit('take_turn',nextUpdate(characterThatEndedTurn));
);
);
请轻点,我大约一周前才开始使用 Node.js。谢谢!
【问题讨论】:
你能发布完整的错误信息吗? 编辑问题以包含它,它是:“events.js:72 throw er; //Unhandled 'error' event RangeError: Maximum call stack size exceeded”。 【参考方案1】:找到我的问题。
我试图通过网络发送的对象(temp)(在 socket.emit('roll_result',temp); 中)是一个自引用数组。正是数组的递归属性导致堆栈超出了最大大小。
【讨论】:
感谢您添加问题的原因,只是在尝试通过 socket.io 连接发送自递归对象时遇到了同样的问题,并且不知道是什么导致了最大调用堆栈大小被超越! 哇,今天也遇到了这个问题!如果我没有发现这篇文章,可能又过了一年。大声笑 非常感谢,您解决了我的问题!【参考方案2】:答案很有帮助。谢谢。
我刚遇到同样的问题,想与可能遇到它的任何人分享。
我的代码使用 express.js 并具有以下内容:
io = require('socket.io').listen(server);
......
io.to(socketId).emit('hello', userId:userId, data:data, res:res);
它产生了“超出最大调用堆栈”错误。问题是我不应该通过 socketio 将变量“res”发送给客户端。我想如果我这样做会导致一些递归行为。
解决方案只是从 emit 语句中删除“res”:
io.to(socketId).emit('hello', userId:userId, data:data);
【讨论】:
【参考方案3】:我有同样的问题。 对我来说,问题是我在套接字上发出的对象包含对套接字本身的引用。所以我基本上是在套接字内发送一个套接字。不要在家里尝试这个:)
【讨论】:
【参考方案4】:当我点击提交按钮时,我遇到了同样的错误。它被禁用并抛出“超出最大调用堆栈大小”。我重新启动了浏览器,它起作用了..奇怪的行为
【讨论】:
【参考方案5】:我想分享我在同一问题上的错误:
public createClient()
this.client = new net.Socket();
this.client.connect(this.port, this.ip, () =>
this.emit("connect");
);
this.client.on("data", (data) =>
this.emit("data", data);
);
this.client.on("close",function () =>
this.emit("close");
);
在关闭事件中,使用正常函数和this(错误原因)导致关闭事件发出循环,结果是堆栈大小错误。
this.client.on("close", () =>
this.emit("close");
);
使用箭头函数。 (或将真实的 this 复制到 _this 之类的东西中并使用内部函数)解决了问题。
这实际上是对函数上下文(在回调中)的无知,或者疏忽..
【讨论】:
【参考方案6】:我遇到了同样的问题,因为我发送了 3 个对象,我通过只发送一个对象解决了这个问题
【讨论】:
【参考方案7】:我也遇到了同样的问题,但就我而言,这有点有趣,因为我实际上是在我的 catch
块中发出错误事件 socket.on("error", new Error(err))
。由于error
是一个私人事件,因此只需更改发出的事件即可修复它。哈哈
【讨论】:
【参考方案8】:就我而言,我不小心通过 socket.io 发送了Promise
【讨论】:
【参考方案9】:我在使用 Socket.io、express 服务器和 p5.js 库制作实时白板应用程序时遇到了同样的问题。 我试图使用套接字将 p5 矢量发送到服务器,导致错误。
这是我的代码
txtPos = createVector(mouseX / width, mouseY / height); let data = pos: txtPos, txt: "", h: colorSlider.value(), b: brighSlider.value(), size: sizeSlider.value(), ; texts.push(data); socket.emit("newText", data);
^ 上面的代码会抛出一个错误,因为我要发送的数据对象包含 txtPos(p5 vector),其中包含 p5 对象,其中包含 p5 向量,p5 向量再次包含 p5 对象,并且它会永远持续下去。 ..就像一个递归对象(循环对象)。
要解决这个问题,我的新代码非常简单。
我换了
pos:txtPos,
与
pos: x:txtPos.x, y:txtPos.y,
猜猜我现在能够成功发送这些数据。 :D
【讨论】:
虽然你遇到的错误很相似,但问题和解决方案的上下文与OP的问题不同。此外,它不会为现有答案增加任何新价值。请考虑遵循答案指南:vi.stackexchange.com/help/how-to-answer。最好的。以上是关于Node.js + Socket.io 超出最大调用堆栈大小的主要内容,如果未能解决你的问题,请参考以下文章
Node.js + Socket.io 内存泄漏和最大监听器
Node.js + socket.io 确定每个实例的最大客户端数量