0

I'm creating an application (chat app) and I'm pushing each username to an array. Using socket.io, whenever I call an event to push the username to the client side array, multiple instances of the array are created.

For example, the first user I log is fine, Then when another user is added, the array will double, then triple and so on. Thank you in advance for the help . The emit event in which I'm doing this is in the USERS_CONNECTED event.

I am also sorry for the terrible sloppiness of the code below.

Server

const express = require('express');
const fs = require('fs');
const path = require('path');
const http = require('http');
const socketIO = require('socket.io');

const publicPath = path.join(__dirname, 'public');
const port = process.env.PORT || 3001;
let app = express();
let server = http.createServer(app);
var io = socketIO(server);
let username;
app.use(express.static(publicPath));
let usersOnline = []; //keeps track of current users online

io.on('connection', (socket) => {
let user = socket.id;
socket.emit('user', user);

    socket.id = "anon";

    socket.on('new user', function(data,callback) {
        //if user name is taken
        if(usersOnline.indexOf(data) != -1 || data == ''){
            callback(false);
        }else{
            //if username is not taken
            callback(true);
            socket.id = data;
            username = data;
            //pushes data(username) to data
            usersOnline.push(socket.id);
            //sends back to client usersOnline array
            io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
            console.log(usersOnline.length)
        }
    });
    socket.on('disconnect', () => {
        usersOnline.splice(usersOnline.indexOf(socket.id), 1);
        //emits count users, sets current user
        io.sockets.emit('USERS_CONNECTED', {usersOnline: usersOnline, user: socket.id});
        console.log(usersOnline.length)

    });


    socket.on('send msg' , function(data){

        io.sockets.emit('send msg', {msg: data, user: socket.id});
    })



});

server.listen(port, () => {
    console.log('server is running master')
});

Client

let socket = io();
let input = document.querySelector('#input_username');
let form = document.querySelector('form')

let userName_page = document.querySelector(".userName_page");
let chat_page = document.querySelector(".chat_page");
let chatWrapper = document.querySelector(".chat_wrapper")
let counter = document.getElementById("counter");
let users = document.querySelector(".users_online")
let join_btn = document.querySelector(".button-effect")
let msg_input = document.querySelector("#sendMsg");
let btn_send = document.querySelector("#send_btn");
let onlineUsers = [];
let sent_ = document.querySelector(".sent_");
let receive_ = document.querySelector(".receive_");
let newUser_text = document.querySelector(".welcome_box")
let user;
let isTyping = document.querySelector('#isTyping')
let welcome_header = document.querySelector("#welcome_header");

let users_online_container = document.querySelector(".users_online");


join_btn.addEventListener("click", function(e){
    e.preventDefault();
    user = input.value;
    //sets user name to input.value
    socket.emit('new user', input.value, function(data){
        if(data){
            userName_page.style.display = "none"
            chat_page.style.display = "flex";
            welcome_header.innerHTML = input.value + ' has joined the party';
            addAnimation();
        }else{
            if(input.value == ''){
                input.classList.add("input_error");
                let error_msg = document.getElementById('error_input');
                error_msg.innerHTML = '*Invalid, Please Type a Username'
                error_msg.style.display = "block";
                input.style.border = "2px solid #d9534f";

            }else{
                input.classList.add("input_error");
                let error_msg = document.getElementById('error_input');
                error_msg.style.display = "block";
                error_msg.style.border = "2px solid #d9534f"
                error_msg.innerHTML = "Woops, sorry but that user name is already taken, please try again";
            }

        }
    });

    //sets up new user

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

        //counts online users currently
        counter.innerHTML = (data.usersOnline.length + " Online");
        for(let i = 0; i < data.usersOnline.length; i++){
            onlineUsers.push(data.usersOnline);
            let h = document.createElement("h3");
            fish.appendChild(h);
        }
        console.log(onlineUsers)
    });


});

//msg send

btn_send.addEventListener('click', function(){
    socket.emit('send msg', msg_input.value);

});
//checks if enter is pressed, if so emits message to chat
function search(ele) {
    if(event.key === 'Enter') {
        socket.emit('send msg', msg_input.value);
    }
}
//send message events

socket.on('send msg', function(data){
    if(data.user == user){
        //sender logic
            msg_input.value = '';
            let p = document.createElement('p');
            receive_.append(p);
            p.innerHTML = "<span class = 'er'>" + 'You' + "</span>" + ": " + data.msg;
            p.style.textAlign = 'right';
            p.style.backgroundColor = "#5cb85c";
            p.style.justifyContent = "flex-end";
            p.style.paddingRight = "2em";
        }
        else{
            //receiver logic
            msg_input.value = '';
            let p = document.createElement('p');
            receive_.append(p);
            p.innerHTML = "<span class = 'er'>" + data.user + "</span>" + ": " + data.msg;
            p.style.textAlign = 'left';
            p.style.backgroundColor = "#5bc0de";
            p.style.paddingLeft = "2em";
        };

        //makes sure scroll stays at bottom
        receive_.scrollTop = receive_.scrollHeight;
    });
function addAnimation(){
    newUser_text.classList.add("act");
}

$( document ).ready(function(){
    let header = document.querySelector(".feedback");

    var timeout;

    function timeoutFunction() {
        typing = false;
        socket.emit("typing", false);
    }

    $('#sendMsg').keyup(function() {
        typing = true;
        socket.emit('typing', 'typing...');
        clearTimeout(timeout);
        timeout = setTimeout(timeoutFunction, 5000);
    });

    socket.on('typing', function(data) {
        if (data) {
            $('#isTyping').html(data);
            $('#isTyping').classList.add('act')
        } else {
            $('#isTyping').html("");
        }
    });

})

1 Answer 1

1

You should replace whole array on client side instead of push. Just stack trace your code:

Firstable on connection on server side you pushes new user id to usersOnline array and emits that array in object via USERS_CONNECTED event in usersOnline property. Client receives that object and pushes object of users (NOT exactly one new user) to onlineUsers array. So eg. 1 user connects to server, usersOnline array would be:

[ 'user1' ]

Then second user connects to server:

[ 'user1', 'user2' ]

And that array is being sent to user2, that is whole object sent by USERS_CONNECTED event would be:

{ usersOnline: [ 'user1', 'user2' ], user: 'user2' }

Now in client instead of replacing you are pushing whole new array, so instead [ 'user1', 'user2' ] you gets [ [ 'user1', 'user2' ] ]

Sign up to request clarification or add additional context in comments.

3 Comments

Great , This makes alot of sense. How do you recommend I replace the array? onlineUsers.replace(data.usersOnline) ?
Well in the best way I would suggest you to separately send users list to newly connected client and broadcast new user to other online people so then push will really make sense. But if you want to do it that way you can just assign new array to previous variable, i.e. onlineUsers = data.usersOnline. Of course if you don't have direct references to previous array's objects. If you referencing to them just by array's key it should work
ahh okay, I came up with onlineUsers.splice(0, onlineUsers.length, ...data.usersOnline) to create new instances of array . Thank you for all the help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.