刷新后socket.io客户端多次监听同一事件

Posted

技术标签:

【中文标题】刷新后socket.io客户端多次监听同一事件【英文标题】:socket.io client listening to same event multiple times after refresh 【发布时间】:2018-02-08 21:28:20 【问题描述】:

我有一个母版页,其中包含一个项目表,在与服务器成功socket.io 连接后,表数据将不断刷新。

点击表格中的项目时(项目的 id 将传递给服务器),将使用 ajax 加载子视图,并通过侦听来自服务器的事件不断刷新。

现在的问题是,通过选择表中的另一个项目,子视图正在多次监听(即使我在成功的 ajax 操作后清除了子视图(html))。例如,如果您选择 10 个项目,它会侦听 10 次,并且看不到子视图中发生的事情(一切都在快速闪烁)。

app.js (nodejs)

io.on('connection', function (socket) 
    console.log('Client Connected...' + clients[socket.id]);
    // updates master page table.
    socket.emit('data', self.StatusObject(self.allModules));

    socket.on('close', function (err, res) 
        console.log('Client disconnected...' + err + ' ' + res);
    );

    //updates child view.
    socket.on('childData', function (id) 
        var data = self.FindModule(id);
        statusPacketTimer = setInterval(function () 
            socket.emit('publishChildData', self.StatusPacket(id));
        , 1000);
    );
);

masterpage.html (html & jquery)

<table>
    <tr onclick="getContent($id)">
        <td>row_id</td>
        <td>status</td>
    </tr>
</table>

<script>
socket.on('data', function (message) 
    $('#mainTable').find('tr:gt(0)').remove();
    updateTable(message);
);

function getContent(id) 
if (id)
        $.ajax(
            async: true,
            type: 'get',
            cache: false,
            url: 'getContext',
            data:  'id': id ,
            success: function (data, status, moduleData) 
                if (status == 'success') 
                    $('#content').html('').html(data);
                
            
        );
    

</script>

childpage.html(html & jquery)

<div id="content"></div>
<script>
    socket.emit('childData', $('#id').val());
    socket.on('publishChildData', function (data) 
        // replace the data in div with new data
    )
</script>

【问题讨论】:

【参考方案1】:
//updates child view.
socket.on('childData', function (id) 
    var data = self.FindModule(id);
    statusPacketTimer = setInterval(function () 
        socket.emit('moduleData', self.LocateStatusPacket(id));
    , 1000);
);

在此代码中,setInterval 连续。 如果通过socket.emit('moduleData', self.LocateStatusPacket(id));触发子视图渲染

然后它每秒渲染一次

【讨论】:

对不起我的错误,代码中的小改动,再次检查。 @kiro112 @zzzziiiirrrrkkkkkkk 还是一样。你为什么使用setInterval?是延迟更新还是持续更新? 因为我需要一些实时信息根据母版页表中选择的项目一直传输到子视图。如果在表中选择了另一个项目,则应传输有关该子视图的信息。有没有比 setInterval 更好的解决方案。 我目前不确定您是如何实现它的。但我认为这里的问题是由于setInterval,您正在多次渲染子视图。当当前选定的项目发生变化时,可能会删除 setInterval 并触发更新 没有子视图只会在母版页中使用 ajax 操作呈现一次。但是该子视图中的数据将由 socket.io 事件侦听器在一秒钟内多次更新(对于您在母版页中单击的次数)。【参考方案2】:

我有同样的问题。 在socket.on(endpoint, callback) 的每个实例之前,在其前面加上socket.off(endpoint, callback)

<script>
    const dataCallback = function (message) 
        $('#mainTable').find('tr:gt(0)').remove();
        cupdateTable(message);
    ;
    socket.off('data', dataCallback); // Removes existing handler, if present.
    socket.on('data', dataCallback);
</script>

这只会从data 端点中删除dataCallback 回调。如果您想删除与data 端点关联的所有回调函数(拥有多个是完全合法的),那么您可以省略回调参数并简单地执行

<script>
    const dataCallback = function (message) 
        $('#mainTable').find('tr:gt(0)').remove();
        cupdateTable(message);
    ;
    socket.off('data'); // Removes ALL existing handlers for this endpoint.
    socket.on('data', dataCallback);
</script>

【讨论】:

以上是关于刷新后socket.io客户端多次监听同一事件的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io 消息事件多次触发

socket.io vs RethinkDB changefeed

在 socket.io-client 的客户端上向 self 发送事件

Socket.IO与服务器多次连接

socket.io简单总结

socket.io笔记三之子命名空间的socket连接