简体   繁体   English

添加到按钮单击事件时,socket.io发射()不起作用

[英]socket.io emit() doesn't work when added to button click event

My web page in short does the following: 简而言之,我的网页执行以下操作:

  1. establishes a socket using socket.io and through that socket some data comes. 使用socket.io建立一个套接字,并通过该套接字传入一些数据。
  2. Based on this data, rows in a table are created. 基于此数据,将创建表中的行。 Each row contains a button. 每行包含一个按钮。
  3. The function of this button would be to send some data back through the socket. 该按钮的功能是通过套接字发送一些数据。

Server code: 服务器代码:

io = require('socket.io').listen(this.server);
io.of('/iot').use(onWSAuthorize);

function onWSAuthorize(socket, next) {
    socket.on('device_activate', function (msg) {
        console.log('device_activate received');
        onDeviceActivate(msg, socket)
    });
}

Client side: 客户端:

var socket = io('/iot');
socket.on('device', setValue);

    function setValue(msg) {
        devArdID = msg.ardid + "_" + msg.devid;

        if (document.getElementById(devArdID) == null) {
            if (!msg.activated) { /* only put a device if it is not "Activated" */
                devArdID = msg.ardid + "_" + msg.devid;
                trDevName = '<tr id="' + devArdID + '" class="w3-hover-grey"><td>' + devTypeGetName(msg.devType) + '</td>';
                trActions = '<td><button id="' + devArdID + '_activate" class="small green">Activate</button></td></tr>'

                $("#devices").append(trDevName + trActions);
                $("#" + devArdID + "_activate").click(function() {
                    console.log('test');
                    socket.emit('device_activate', {my : 'test'});
                });
                //socket.emit('device_activate', {my : 'test'});
            }
        } else {
            /* the device already reported, structre needs to be filled in with new data */
            updateDeviceStatus(msg);
        }
    }     

Now when I execute the above client code and the setValue() gets triggered by incoming "device" event emitted by the server, row is added to the table - this row contains a button. 现在,当我执行上述客户端代码,并且setValue()被服务器发出的传入“设备”事件触发时,该行将添加到表中-该行包含一个按钮。 When I press the button it's anonymous function gets executed and I can see "test" string appearing in the browser's console. 当我按下按钮时,它的匿名函数被执行,并且我可以看到“ test”字符串出现在浏览器的控制台中。 However it looks like socket.emit() is not executed. 但是,看起来好像socket.emit()没有执行。

How do I know it is not executed? 我怎么知道它没有执行? So When I uncoment line with next socket.emit() below (it will be executed during setValue() execution) I can see that it gets executed as on the server I see that onDeviceActivate() is executed so the "device_activate" event is received at the server side. 因此,当我与下面的下一个socket.emit()断开连接时(它将在setValue()执行期间执行),我可以看到它像在服务器上一样被执行,我看到onDeviceActivate()已执行,因此“ device_activate”事件为在服务器端收到。

Could you tell me please what I could be doing wrong here? 你能告诉我我在这里可能做错了什么吗? Why socket.emit() doesn't work on button press? 为什么socket.emit()在按下按钮时不起作用? I don't see any exception in the browser console. 我在浏览器控制台中看不到任何异常。

You put socket.emit() inside a .click() handler. 您将socket.emit()放在socket.emit() .click()处理函数中。 It won't get called until sometime later (if ever) when that object in the page actually gets clicked. 直到稍后(如果有的话)某个页面中的对象实际被单击时,它才会被调用。

.click() handlers (as with nearly all event handlers) are non-blocking and asynchronous and they get called some indeterminate time in the future. .click()处理程序(几乎与所有事件处理程序一样)是非阻塞且异步的,它们在将来会被称为不确定的时间。

This code also has another potential problem if the client receives more than one device message, then each time you get one, you will add yet another .click() handler so that when that item is actually clicked, you may get multiple click handlers all firing on the same event. 如果客户端收到多个device消息,则此代码还存在另一个潜在问题,那么每次您收到一条device消息时,您都会添加另一个.click()处理函数,以便当实际单击该项目时,您可能会获得多个单击处理程序。在同一事件上触发。 That is pretty much never what you want. 那几乎永远不是您想要的。

If you had explained in more detail in your question what overall problem you were actually trying to code, we could perhaps suggest a better way to structure your code that does not have this issue. 如果您已在问题中更详细地说明了您实际上要尝试编写的总体问题,我们可能会建议一种更好的方法来构造没有此问题的代码。


Your code is also using a number of undeclared variables. 您的代码还使用了许多未声明的变量。 This is a big bad no-no in Javascript. 这是Java语言中的一个非常糟糕的禁忌。 In fact, if you run your code in strict mode (which you really should), then this will even be an error because it's evil. 实际上,如果您在严格模式下运行代码(这确实应该这样做),那么这甚至将是一个错误,因为它是邪恶的。 When you assign to an undeclared variable such as devArdID , it becomes an implicit global. 当您分配给未声明的变量(例如devArdID ,它将成为隐式全局变量。 That means that multiple calls to the same function can easily overwrite the variable the previous call was using. 这意味着对同一函数的多次调用可以轻松覆盖先前调用所使用的变量。 You should never do this. 您永远不要这样做。

Also declare every single variable you use with var , let or const and declare it in the closest scope you can (usually within the function or block where it is used). 还声明与varletconst一起使用的每个变量,并在可以使用的最接近范围内声明它(通常在使用它的函数或块中)。


Because you're using .use() on the server-side, that is middleware. 因为您在服务器端使用.use() ,所以它是中间件。 You have to call next() after your processing to allow the connection to continue. 您必须在处理后调用next()才能继续连接。 If you don't call next() , then the connection doesn't really happen properly. 如果您不调用next() ,则连接实际上不会正确进行。

io = require('socket.io').listen(this.server);
io.of('/iot').use(onWSAuthorize);

function onWSAuthorize(socket, next) {
    socket.on('device_activate', function (msg) {
        console.log('device_activate received');
        onDeviceActivate(msg, socket)
    });
    // let middleware proceed
    next();
}

I'm not quite sure why you aren't doing this the more traditional way as there does not appear to be any reason for you to be using middleware: 我不太确定为什么您不以更传统的方式执行此操作,因为似乎没有任何理由使用中间件:

io.of('/iot').on('connect', (socket) => {
    socket.on('device_activate', function (msg) {
        console.log('device_activate received');
        onDeviceActivate(msg, socket)
    });
});

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

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