对于我的Node应用程序,我在Debian上运行了一个服务器(app.js),使用socket.io向我的客户端(index.html)提供html和websocket数据。我正在尝试制作基于回合制的HTML5多人游戏。
使用socket.emit()/ io.emit()和socket.on()执行大量成功的数据传输后,我的服务器在socket.emit()调用时崩溃并出现错误
“events.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一周前。谢谢!
答案 0 :(得分:41)
找到我的问题。
我试图通过网络发送的对象(temp)(在socket.emit(&#39; roll_result&#39;,temp);)是一个自引用数组。这是数组的递归属性导致堆栈超过最大大小。
答案 1 :(得分:6)
答案非常有用。感谢。
我遇到了同样的问题,并希望与可能遇到此问题的任何人分享。
我的代码使用express.js并具有以下内容:
io = require('socket.io').listen(server);
......
io.to(socketId).emit('hello', {userId:userId, data:data, res:res});
它生成了#34;超出最大调用堆栈&#34;错误。问题是我不应该发送变量&#39; res&#39;通过对客户的保护。我想如果我这样做会导致一些递归行为。
解决方案就是删除&#39; res&#39;来自emit语句:
io.to(socketId).emit('hello', {userId:userId, data:data});
答案 2 :(得分:0)
这是我遇到的同一个错误,当我点击提交按钮时。它被禁用并投掷&#34;超出最大调用堆栈大小&#34;。我重启了我的浏览器,它工作..奇怪的行为
答案 3 :(得分:0)
我想在同一问题上分享我的错误:
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.client.on("close", () => {
this.emit("close");
});
使用箭头功能。 (或将真实的内容复制到_this这样的内容中并使用内部函数)解决了问题。
这实际上是对函数上下文(在回调中)或疏忽大意的无知。
答案 4 :(得分:0)
我有同样的问题。 对我来说,问题在于我在套接字上发射的对象持有对套接字本身的引用。所以我基本上是在套接字内发送一个套接字。不要在家尝试:)
答案 5 :(得分:0)
我遇到了同样的问题,这是因为我发送了3个对象,而我只通过发送一个对象解决了这个问题
答案 6 :(得分:0)
我也遇到同样的问题,但就我而言,这有点可笑,因为我实际上是在socket.on("error", new Error(err))
块中发出了错误事件catch
。由于error
是私有事件,因此仅通过更改发出的事件即可解决。哈哈
答案 7 :(得分:0)
就我而言,我不小心通过 socket.io 发送了 Promise
答案 8 :(得分:-1)
我在使用 Socket.io、express server 和 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