Node sends data back multiple times everytime a user adds new data

时间:2015-10-30 22:33:56

标签: javascript node.js socket.io

First of all, I would like to apologize for the horribly worded title; I have been trying to think of one for the past 20 minutes but I do not know a succinct way to describe the problem I am having. If anyone has a better suggestion, please let me know or edit the title if you are able to.

Background: In order to learn NodeJS, I am creating a chat server. When the user clicks the createRoomBtn, an event is created containing the name of the room the user just created, and sent to the socket.js module in app.js, app.js then appends the room to the array of rooms (these rooms are displayed as a list in the browser), and creates a broadcast event to all users including the active user.

Problem: Let's say there is an empty list, and user adds a new room, titled "NodeJS", this will display the room on the screen, and everything is fine and dandy. Now, if I was to add another room, Socket.io, for example, the browser renders the following result: Socket.io, NodeJS, NodeJS. If I was to add "Javascript", the result would be Javascript, Socket.io, NodeJS, Socket.io, Node.JS. Basically, the browser renders the list over and over again, and each time the list shrinks by one. I do not have the slightest idea of why this is happening. The weird thing is that if I press refresh, the browser renders the list correctly Javascript, Socket.io, NodeJS. What is going on?

socket.js:

module.exports = function(io, rooms) {
    var chatrooms = io.of('/roomlist').on('connection', function(socket) {  //io.of creates a namespace 
        console.log('Connection established on the server');
        socket.emit('roomupdate', JSON.stringify(rooms));   


        socket.on('newroom', function(data) {
            console.log(data);
            rooms.push(data);
            socket.broadcast.emit('roomupdate', JSON.stringify(rooms)); 
            socket.emit('roomupdate', JSON.stringify(rooms));   

        })      
    })

    var messages = io.of('/messages').on('connection', function(socket) {   
        console.log('Connected to the chatroom!');

        socket.on('joinroom', function(data) {
            socket.username = data.user; 
            socket.userpic = data.userPic;
            socket.join(data.room);         
        })

        socket.on('newMessage', function(data) {

            socket.broadcast.to(data.room_number).emit('messagefeed', JSON.stringify(data));  
        })
    })
} 

chatrooms.html:

<!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>{{title}}</title>
        <link rel="stylesheet" href="../css/chatrooms.css">
        <script src="//code.jquery.com/jquery-1.11.0.min.js"> </script> 
        <script src="/socket.io/socket.io.js"> </script> 
        <script>
        $(function() {
            var host = '{{config.host}}';       
            var socket = io.connect(host + '/roomlist');

            socket.on('connect', function() {
                console.log('connection established');      
            })  
            socket.on('roomupdate', function(data) {
                $('.roomlist').html('');

                var procData = JSON.parse(data); 

                for (var i = 0; i < procData.length; i++) { 
                    var str = '<a href="room/' + procData[i].room_number + '"><li>'
                    + procData[i].room_name + '<li></a>'; 
                    $('.roomlist').prepend(str);

                    console.log(str);

                }
            }) 

            $(document).on('click', '#createRoomBtn', function() {
                var room_name = $('#newRoomText').val();
                console.log(room_name);
                if (room_name != '') {
                    var room_number = parseInt(Math.random() * 10000);
                    socket.emit('newroom', {room_name: room_name, room_number: room_number});
                    $('#newRoomText').val('');                  
                }
            }) 
        }) 

        </script>
    </head>  

<body>

    <div class="cr-userbox">
        <img src="{{user.profilePic}}" class="userPic">
        <h3 class="username">{{user.fullName}}| <a href="/logout">Logout</a></h3>
    </div>


    <div class="cr-container">
        <h1> ChatRooms</h1>
        <div class="cr-newroom">
            <input type="text" id="newRoomText" autocomplete="off">
            <input type="submit" id="createRoomBtn" value=" Create Room">
        </div>

        <div class="cr-roomlist">
            <ul class="roomlist">
            </ul>
        </div>
    </div>
</body>
</html>

Please let me know if more information/modules are required, and I will be happy to provide them.

Update1: As correctly suggested by alex-rokabilis, I have changed $('.roomlist').html() = '' to $('.roomlist').html(''), however, the problem continues to persist.

2 个答案:

答案 0 :(得分:1)

我不确定这是否是您问题的原因,但是您已经获得了嵌套列表条件,因为您的socket中有两个打开的<li>标签。(&#39 ; roomupdate&#39;)功能

答案 1 :(得分:0)

我认为问题是如何在html部分渲染房间,而不是socket.io如何发送数据。 你使用$('.roomlist').html='';,但这没有做任何事情! .html是jquery中的一个函数,所以正确的做法是$('.roomlist').html('');

所以基本上你没有删除以前的房间,而只是添加了更多的重复。另外我注意到这不是你问题的一部分,在你使用的nodejs代码中:socket.broadcast.emit('roomupdate', JSON.stringify(rooms)); socket.emit('roomupdate', JSON.stringify(rooms));

如果你想向所有连接的客户端广播一些东西,它有一个功能,而且你也不需要对你的数据进行字符串化,socketio会在内部为你做这个!所以你可以使用这样的东西: io.emit('roomupdate',rooms);