Javascript 如何阻止socket.io发射多次

Javascript 如何阻止socket.io发射多次,javascript,node.js,socket.io,Javascript,Node.js,Socket.io,我目前正在使用node.js和socket.io在线制作rpg。在我开始制作碰撞检测系统之前,一切都很顺利。我在网上寻找解决方案,发现有人有类似的问题,但不知道如何解决我的问题。下面是我的代码 客户端: function move_character(x){ //socket.io start var collision = io.connect('/collision'); collision.emit('detection', x);

我目前正在使用node.js和socket.io在线制作rpg。在我开始制作碰撞检测系统之前,一切都很顺利。我在网上寻找解决方案,发现有人有类似的问题,但不知道如何解决我的问题。下面是我的代码

客户端:

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
    }
服务器端:

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();
            });
    });
});
在服务器端,emit总是发送true,并且坐标位于固定点,我这样做是为了帮助调试。您可能还会发现现在没有使用的代码,我将来也会使用它,但我想先修复这个bug

我的实际问题是,当我第一次移动角色时,一切正常,但第二次移动会再次执行第一次,然后执行第二次,第三次移动会执行第一次、第二次和第三次移动。当我移动精灵10次时,它正在重复第10步之前的前9个步骤,并在整个屏幕上移动

我确实试图通过修改代码和添加console来找到解决方案。日志无处不在。我发现,如果我在服务器端发出[true,x]并适当地修复客户端,精灵将朝我想要的方向移动,但n时间数n是我尝试的移动数(第一次移动1,第四次移动4)。刷新确实会使一切恢复正常。我还尝试将io.connect('/collision')移动到函数外部,但也不起作用。问题似乎是服务器端的emit保存了过去发送的数据的历史记录,然后在每次调用时重新发送。也可能是客户端上的collision.on导致了错误


此外,在服务器端,它所做的是检查DB是否可以将所讨论的磁贴移动到,如果是,则为true,如果不是,则为false。由于该错误,它再次设置为true。当bug消失后,我将完成服务器端代码。

您的问题是,每次调用
move\u character(x)
,您都会创建一个新的socket.io连接,并使用它的关联事件处理程序。因此,第一次调用它时,它连接并设置一个事件处理程序,
发出('detection',x)
,然后设置一个事件处理程序来侦听响应

第二次调用
move_character(x)
,您将创建另一个socket.io连接并执行相同的操作。现在,当服务器收到消息时,它会执行一些数据库工作,然后将响应广播到所有连接的套接字。因此,既然在同一浏览器窗口中有两个socket.io连接,那么每个连接都会得到响应,并且会被多次处理

第三次,你又设置了一个,等等


要修复此问题,如果您创建一个socket.io连接,然后将其用于与该名称空间的所有通信,那么socket.io工作得最好。因此,将socket.io连接的创建和事件处理程序的添加移到
move_character(x)
函数之外,使其只发生一次

在服务器上,我不太明白为什么要在数据库工作后向所有连接的客户端广播响应。我想您可能只想响应发送查询的连接。您可以通过更改以下内容来完成此操作:

collision.emit('col', true);


每次调用
move\u character()
,都会添加另一个socket.io连接。我最终将服务器部分更改为socket,我没有意识到两者之间存在差异,并且我将服务器中的数据更改为数组。在客户端,我去掉了函数中除emit之外的所有内容,现在它可以在您的帮助下工作。
socket.emit('col', true);