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

时间:2017-07-16 21:41:27

标签: javascript node.js socket.io

我的网页简要介绍了以下内容:

  1. 使用socket.io建立一个套接字,然后通过该套接字创建一些数据。
  2. 根据此数据,创建表格中的行。每行包含一个按钮。
  3. 此按钮的功能是通过套接字发回一些数据。
  4. 服务器代码:

    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)
        });
    }
    

    客户方:

    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);
            }
        }     
    

    现在,当我执行上述客户端代码并且setValue()被传入的&#34;设备&#34;触发时由服务器发出的事件,行被添加到表中 - 该行包含一个按钮。当我按下按钮时,它的匿名功能被执行,我可以看到&#34; test&#34;字符串出现在浏览器的控制台中。但是看起来socket.emit()没有被执行。

    我怎么知道它没有被执行?所以当我用下面的socket.emit()解开行时(它将在setValue()执行期间执行)我可以看到它在服务器上执行我看到onDeviceActivate()被执行所以&#34; device_activate& #34;在服务器端收到事件。

    请问我能在这里做错什么?为什么socket.emit()不能按下按钮?我在浏览器控制台中看不到任何异常。

1 个答案:

答案 0 :(得分:1)

您将socket.emit()放入.click()处理程序中。直到某个时候(如果有的话)页面中的对象实际被点击时才会被调用。

.click()处理程序(与几乎所有事件处理程序一样)是非阻塞和异步的,并且将来会被称为一些不确定的时间。

如果客户端收到多条device消息,此代码还有另一个潜在问题,那么每次获得一条消息时,您将添加另一个.click()处理程序,以便在实际点击该项时,您可能会在同一事件中触发多个点击处理程序。这绝不是你想要的。

如果您在问题中更详细地解释了您实际尝试编码的整体问题,我们或许可以建议一种更好的方法来构建没有此问题的代码。

您的代码也使用了许多未声明的变量。这在Javascript中是一个很糟糕的禁忌。事实上,如果你以严格模式运行你的代码(你真的应该这样),那么这甚至会是一个错误,因为它是邪恶的。当您分配到未声明的变量(例如devArdID)时,它将变为隐式全局变量。这意味着对同一函数的多次调用可以轻松覆盖先前调用所使用的变量。你永远不应该这样做。

同时声明与varletconst一起使用的每个变量,并在最接近的范围内声明它(通常在使用它的函数或块中)。

因为您在服务器端使用.use(),即中间件。您必须在处理后调用next()以允许连接继续。如果你没有打电话给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();
}

我不太确定你为什么不这样做更传统的方式,因为你似乎没有任何理由使用中间件:

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