简体   繁体   English

如何停止socket.io发射一次以上

[英]How to stop socket.io emit from firing more then once

I am currently working on making an rpg online using node.js and socket.io. 我目前正在使用node.js和socket.io在线制作rpg。 Everything was working fine until I started making a collision detection system. 一切正常,直到我开始制造碰撞检测系统。 I looked online for a solution and found people that had similar issues but could not understand how to fix my issue. 我在网上寻找解决方案,发现遇到类似问题但不了解如何解决问题的人。 The following is my code. 以下是我的代码。

client side: 客户端:

function move_character(x){
        //socket.io start
        var collision = io.connect('/collision');
        collision.emit('detection', x);
        collision.on('col', function (msg) {
            if(msg == true) {
                if (x == 'up') {
                    $('#sprite').animate({'top': '-=50px'},150);
                } else if (x == 'down') {
                    $('#sprite').animate({'top': '+=50px'},150);
                } else if (x == 'left') {
                    $('#sprite').animate({'left': '-=50px'},150);
                } else if (x == 'right') {
                    $('#sprite').animate({'left': '+=50px'},150);
                }
            }
        });
        //socket.io end
    }

server side: 服务器端:

var collision = io.of('/collision');
collision.on('connection', function (socket) {
    socket.on('detection', function (x) {
        pool.getConnection(function (err, con) {
            con.query('SELECT class_state FROM gmaps LIMIT 1',
                function (err, result) {
                    if (err) throw err;
                    else {
                        var mapState = result[0].class_state.split(",");
                        var x_coord = 6;
                        var y_coord = 5;

                        var id = ((y_cord -1)*10)+(x_cord -1);
                        var index;
                        if(x == 'up'){
                            index = id-10;
                        }else if(x == 'down'){
                            index = id+10;
                        }else if(x == 'left'){
                            index = id-1;
                        }else if(x == 'right'){
                            index = id+1;
                        }
                        collision.emit('col', true);
                    }
                    });
                con.release();
            });
    });
});

On the server side the emit is always sending true and the coordinates are at a fixed point, I did that to help with the debugging. 在服务器端,emit始终发送true,并且坐标位于固定点,我这样做是为了帮助调试。 You may also find code that is not being used right now and I will be using it in the future but I want to fix this bug first. 您可能还会发现目前未使用的代码,将来我会使用它,但是我想先修复此错误。

My actual problem is that when I move the character the 1st time, everything works but the 2nd move does the 1st again followed by the 2nd with the 3rd doing the 1st, 2nd then 3rd move. 我的实际问题是,当我第一次移动角色时,一切正常,但是第二步再次执行第一步,随后进行第二步,第三步进行第一步,第二步然后是第三步。 By the the time I have moved the sprite 10 times, it is repeating the 1st 9 steps before step 10 and it is going all over the screen. 到我将精灵移动10次时,它正在重复第10步之前的第9个步骤,并且遍及整个屏幕。

I did try to find the solution myself by changing the code and adding console.log's everywhere. 我确实尝试通过更改代码并在各处添加console.log来找到解决方案。 I found that if I emit [true,x] on the server side and fix the client side appropriately, the sprite will move in the direction I want but n number of time with n being the number of moves I tried (1 for 1st move, 4 for 4th move in the same direction). 我发现,如果我在服务器端发出[true,x]并适当地修复客户端,则精灵将朝我想要的方向移动,但是n次,其中n是我尝试的移动次数(第1步为1 ,则4代表相同方向的第4个移动)。 Refreshing does set everything back to normal as it should. 刷新确实会使一切恢复正常。 I also tried moving io.connect('/collision') outside of the function but that did not work either. 我也尝试将io.connect('/ collision')移到函数之外,但这也不起作用。 It seems the problem is the emit on the server side is keeping a history of past data that has been sent and then resending it each time a call is made. 看来问题出在服务器端,发射端保留了过去已发送数据的历史记录,然后在每次调用时重新发送。 It could also be the collision.on on the client side that is causing the bug. 也可能是客户端上的冲撞导致该错误。

Also, on the server side, what it does is checks the DB if the tile in question is able to be moved on to, if yes then true and if not then false. 同样,在服务器端,它的作用是检查数据库是否可以将所涉及的图块移至该图块,如果是,则为true,否则为false。 It is set to true again because of the bug. 由于该错误,再次将其设置为true。 When the bug is gone I will finish the server side code. 当错误消失后,我将完成服务器端代码。

Your issue is that every time you call move_character(x) , you create a new socket.io connection with it's associated event handlers. 您的问题是,每次调用move_character(x) ,都会使用与其关联的事件处理程序创建一个新的socket.io连接。 So, the first time you call it, it connects and sets up an event handler, does the emit('detection', x) , then sets up an event handler to listen for the response. 因此,第一次调用它时,它会连接并设置一个事件处理程序,执行emit('detection', x) ,然后设置一个事件处理程序以侦听响应。

The second time you call move_character(x) , you create another socket.io connection and do the same. 第二次调用move_character(x) ,您将创建另一个socket.io连接并执行相同的操作。 Now, when your server gets the message, it does some database work and then broadcasts the response to all connected sockets. 现在,当服务器收到消息时,它将执行一些数据库工作,然后将响应广播到所有连接的套接字。 So, now that you have two socket.io connections in the same browser window, each connection gets the response and it gets processed multiple times. 因此,既然您在同一个浏览器窗口中有两个socket.io连接,则每个连接都将获取响应,并且它会被处理多次。

The third time, you set up yet another and so on... 第三次,您设置了另一个,依此类推...


To fix, socket.io works best if you create one socket.io connection and then use it for all your communication to that namespace. 要修复,如果您创建一个socket.io连接,然后将其用于与该名称空间的所有通信,则socket.io的工作效果最佳。 So, move the creation of the socket.io connection and the addition of the event handler outside of your move_character(x) function so it only happens once. 因此,将socket.io连接的创建和事件处理程序的添加move_character(x)函数之外,因此它只发生一次。

And on the server, I don't quite understand why you are broadcasting the response after your database work to ALL connected clients. 在服务器上,我不太了解为什么您的数据库工作后向所有连接的客户端广播响应。 I would think you would want to respond to only the connection that sent the query. 我认为您只想响应发送查询的连接。 You can do that by changing: 您可以通过更改以下内容来做到这一点:

collision.emit('col', true);

to

socket.emit('col', true);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM