Update array without having to wait for another user to log in

Asked

Viewed 28 times

-2

I am chatting with Node.js and socket.io, I have an error in listing the values of an array, the array of users. I put a <ul></ul> with an id and nothing else. follow the prints below (the code on the left is the server and the one on the right is the client): this is the server:


io.on('connection', (socket) => {

    Msg.find().then(result => {
        socket.emit('output-messages', result)
    })

    /*User.find().then(result => {
        socket.emit('output-users', result)
    })*/

    socket.on('userConnected', (data) => {
        /*const userdb = new User({
            username: data.username
        });
        userdb.save().then(()=>{
            io.emit('displayUsers', data)
        }).catch(err =>{
            console.log("o erro foi: " + err)
        });*/

        io.emit('displayUsers', { users: users })


        users[socket.id] = data.username

        console.log(users)
    });

    socket.on('chat message', (data) => {
        const messagedb = new Msg({
            username: data.username,
            msgstring: data.msgstring
        });
        messagedb.save().then(()=>{
            io.emit('chat message', data)
        }).catch(err =>{
            console.log("o erro foi: " + err)
        });
        console.log(data)
    });


    socket.on('disconnect', function() {
        try{
            delete users[socket.id]
            io.emit('disconnection', {users: users})
        }
        catch(err){
            console.log(err)
        }
        console.log(users)
    });
});

and this is the client:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat da galera</title>

    <link 
        href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
        rel="stylesheet" 
        ntegrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" 
        crossorigin="anonymous"
    >
    <script 
        src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" 
        crossorigin="anonymous"
    ></script>

    <style>
        body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
  
        #form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 15%; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
        #input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
        #input:focus { outline: none; }
        #form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
  
        #messages { list-style-type: none; padding: 0; margin-left: 15%; }
        #messages > li { padding: 0.5rem 1rem; }
        #messages > li:nth-child(odd) { background: #efefef; }
        .namep{
            margin:0;
            padding: 0.5rem 1rem;
            color: rgb(10, 10, 10);
            background-color: rgb(180, 180, 180);
            font-size: 20px;
        }
        .namep2{
            margin:0;
            padding: 0.5rem 1rem;
            color: rgb(0, 0, 0);
            background-color: rgb(255, 255, 255);
            font-size: 25px;
        }
        #usersOnline{
            position: fixed;
            width: 15%;
            height: 100%;
            backdrop-filter: blur(10px);
            background: rgba(0, 0, 0, 0.15);
            bottom: 0;
            left: 0;
        }
        .usersH1{
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="usersOnline">
        <h1 class="usersH1" id="usersH1"></h1>
        <ul id="users"></ul>
    </div>
    <ul id="messages"></ul>
    <form id="form" action="">
      <input id="input" autocomplete="off" /><button>Send</button>
    </form>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        var name = window.prompt("Your username:")

        if(name == null){
            alert("Please insert a valid name!");
            location.reload();
        };


        var socket = io();

        var messages = document.getElementById('messages');
        var usersUl = document.getElementById('users');
        var usersTitle = document.getElementById('usersH1');
        var form = document.getElementById('form');
        var input = document.getElementById('input');


        form.addEventListener('submit', function(e) {
            e.preventDefault();
            if  (input.value) {
                socket.emit('chat message', {
                    username: name,
                    msgstring: input.value
                });
                input.value = '';
            }
        });

        socket.emit('userConnected', {username: name});
        socket.emit('disconnection', {username: name});

        socket.on('output-messages', data => {
            console.log(data)
            if (data.length) {
                data.forEach(message => {
                    appendUsers(message.username)
                    appendMessages(message.msgstring)
                });
            };
        });

        /*socket.on('output-users', data => {
            console.log(data)
            if (data.length) {
                data.forEach(message => {
                    appendUsersTab(message.username)
                });
            };
        });*/

        socket.on("displayUsers", function(data){
            let county = Object.keys(data.users).length

            usersTitle.textContent = 'Users (' + [county + 1] + ')'; 
            //usersUl.textContent = '' + data.users + ''; 
            usersUl.textContent = Object.values(data.users)
        });

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

            console.log(data.users)
        });

        socket.on('chat message', function(obj) {
            let nameP = document.createElement('p');
            nameP.className = "namep"
            nameP.textContent = obj.username + ":";
            
            let item = document.createElement('li');
            item.textContent = obj.msgstring

            messages.appendChild(nameP);
            messages.appendChild(item);
            window.scrollTo(0, document.body.scrollHeight);
        });

        function appendUsersTab(message) {
            const html = `<p>${message}:</p>`
            usersUl.innerHTML += html
        }

        function appendUsers(message) {
            const html = `<p class="namep">${message}:</p>`
            messages.innerHTML += html
        }
        

        function appendMessages(message) {
            const html = `<p style=" padding:0.5rem 1rem; ">${message}</p>`
            messages.innerHTML += html
        }
    </script>
</body>
</html>

The array only updates when a user enters, which causes the <ul> users only appear when another user enters, e.g.: there in the image, only appeared the user of John when Peter entered, and only appeared the Peter when Joseph entered, and only the Joseph will appear if another user enters:

(the problem is in the part of users) telas dos clients conectados

  • 1

    bro, pq q td world vote negative on my question, this will not help me at all, I thought the stackoverflow was to help people who are beginners or have some doubt, then comes the person and votes negative thinking it will help me in something, Not only does it take away my reputation. What a rage, bro!!!!

  • 2

    "i thought stackoverflow was to help people who are beginners or have any questions" - It’s not individual help. And on the negative side, he is the one who makes the site useful, making the important infomation stand out, and the problematic mess less (see [Tour]). To understand what kind of question serves the site and, consequently, avoid closures and negativities worth reading What is the Stack Overflow and the Stack Overflow Survival Guide (summarized) in Portuguese.

  • 2

    Posting a [mcve] in place of the original code can help a lot as well. For more details have [help] and the Community FAQ, I hope that with these links I can better enjoy the site, and at the same time provide questions that add more to our collective knowledge repository. Questions and answers (even if correct) that only serve the specific case of its author end up playing the role of Helpdesk, and completely escape the purpose of the site (even if they solve the problem of the author, do not fulfill the purpose).

  • Man, I still don’t get this site, man, I got downvote and it didn’t help me at all, but thanks for understanding.

  • Then take it easy on the past links, I think you’ll get the hang of it over time, and get the hang of it. Normal at first to have some friction, quite user has (and I think the site is advertised in a wrong way). Once the person understands the true goal of the site (which is a repository of knowledge where each post can help other people, and how to do that), it becomes easier (many have gone through it and then joined). As I commented, negative is only classification, do not worry. It is not personal (it is not equal like, social network, it is only technical classification).

  • I’ve seen your user in a vote for moderators, mt mass

Show 1 more comment

1 answer

1


The problem is here:

io.emit('displayUsers', { users: users })
users[socket.id] = data.username

When a user enters, you transmit the list of users to everyone before to enter the new user.

Here’s what’s going on:

  1. users initially empty
  2. Peter enters
  3. Is transmitted to users (empty) for all
  4. Peter is inserted in users
  5. John enters
  6. Is transmitted to users (containing Peter) for all
  7. John is inserted in the users
  8. Joseph enters
  9. Is transmitted to users (containing Peter and John) for all
  10. Joseph is inserted in users

And that’s how we got to the situation described in the last image. Just update the list before to transmit it:

users[socket.id] = data.username
io.emit('displayUsers', { users: users })

This way, when a new user enters, everyone will receive a version of the users that includes the user who just joined.

P.S.: About the downvotes in your question, I also found it unnecessary. I hope you have better experiences here in the future!

P.P.S.: Just a hint... take it much care when inserting content typed by users directly into HTML. Your Handler for new messages takes care of this by using the textContent, but the appendMessages inserts directly, without filtering, and this is dangerous.

  • 1

    THANK YOU, FOR THE LOVE OF GOD, BROTHER, GOD BLESS YOU

Browser other questions tagged

You are not signed in. Login or sign up in order to post.