0

I am building a simple chat system and I have a function that will broadcast to all clients the list of online users. This is working well but I run this function every minute and it sends the list back even if nothing has changed. I am trying to implement a check to see if the list has changed compared to previous iteration but I am stuck finding a way to perform the comparison.

My first attempt was the following:

var oldUsersList = { type: 'onlineusers', users: [] };

// Update online users list, specially if someone closed the chat window.
function updateOnlineUsers() {
    const message = { type: 'onlineusers', users: [] };

    // Create a list of all users.
    wss.clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
            message.users.push({ id: client.id, text: client.username, date: client.date });
        }
    });
    console.log(oldUsersList);
    console.log('message '+message);
    if(oldUsersList.users==message.users){
        console.log('match');
    }else{
        oldUsersList=message;
        // Send the list to all users.
        wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(JSON.stringify(message));
            }
        }); 
    }
}

but i face two different issues:

  • console.log(oldUsersList); will echo { type: 'onlineusers', users: [] }; and to me it looks like js is considering it as a string while console.log('message '+message); will echo [object Object] as expected

  • if(oldUsersList.users==message.users) will never return true even if the two are equals.

What is the right way to check if the list of users have changed?

Lelio Faieta
  • 6,457
  • 7
  • 40
  • 74
  • 1
    Does this answer your question? [How to compare arrays in JavaScript?](https://stackoverflow.com/q/7837456/328193) – David Apr 17 '23 at 15:21
  • It seems like you're collecting a ton of data here to compare. Why not just a list of `id` values? – tadman Apr 17 '23 at 15:21
  • 1
    How many places in your code make changes to this list? Could they set an explicit indication that they just changed the list? – user1686 Apr 17 '23 at 15:24
  • `console.log('message '+message)` here you are coercing the variable message to a string ([object Object]) by adding it to an existing string with `+`. `console.log('message', message)` would not do that. – James Apr 17 '23 at 15:25
  • Have a bool variable that changes to TRUE/FALSE to idicate whether message has been updated and thus list needs to be updated – Onyambu Apr 17 '23 at 15:27
  • @Onyambu you still have to determine if the list have been updated... and we are back to my issue – Lelio Faieta Apr 17 '23 at 15:28
  • @user1686 there are no places where my code changes the list: it is created dinamically inside this function. So that's why i'd compare it to it's previous version – Lelio Faieta Apr 17 '23 at 15:30
  • @LelioFaieta: I was talking about the _original_ list from which yours is created, i.e. the `wss.clients` list. What adds/removes clients and what changes `readyState` for each client? (If the runtime does it, is there an option to set up a callback when readyState changes?) – user1686 Apr 17 '23 at 15:31
  • 2
    Make a `Set` of client user IDs. Then you can use `Set.difference()` to see if the set has changed. – Barmar Apr 17 '23 at 15:32
  • @LelioFaieta just have the variable change to true anytime the list is modified. and you can always have the variable everyplace the list is being modified – Onyambu Apr 17 '23 at 15:47
  • @Barmar thanks, this is exactly what I was looking for. I'm implementing your suggestion and it works with just a few lines of code! Thanks for the lesson I've just learned – Lelio Faieta Apr 17 '23 at 16:37
  • Feel free to post your final code as an answer. – Barmar Apr 17 '23 at 16:42

3 Answers3

0

here's the array implementation it checks if all the members of new user IDs are present in the Old user IDs in this way if the new user has joined the list of newUserIDs, doesOldUserListChanged will be true.

const doesNewUserJoined = newUserIDs.some(val => OldIDs.indexOf(val) === -1)

if members of the list exit the chat you can use the following as well

const doesOldUserexited = OldIDs.some(val => newUserIDs.indexOf(val) === -1)

AhmadDeel
  • 326
  • 4
  • 13
0

After digging into Set as suggested by @Barmar I ended up using Json.stringify() because on Set comparison I haven't found a working solution to find an exact match between the two list but only solution where you check one list against another and this will provide a wrong result to me if the list to compare against have more users then the new one

The caveat for this solution is that the keys must be in the same order (in my situation they are always). If so you can just do:

JSON.stringify(oldUsersList)===JSON.stringify(currentUsersList)

and this returns true if the two lists contains the same users.

Lelio Faieta
  • 6,457
  • 7
  • 40
  • 74
-2

You have a realtime list of online users that updating after change? If currect you can get stringify all user id like this: 1,2,4,22,55,77 After get convert to array of number, then use foreach for current user list to apply changes.for example:

// convert to array of numbers
Const newUserList = `1,2,4,22,55,77`.split(',').map(Number)

// detect new user become online
Const newOnlineUsers = onlineUsers.filter(user=> newUserList.some(uid => uid ===user.id)

// Remove offline users (that users is not contains in new user list)
onlineUsers = onlineUsers.filter(user=> newUserList.some(uid => uid ===user.id)

// the new users can be fetch more info using send message (once)
newOnlineUsers.forEach(uid => OnlineUsers.push({id: uid})
  • Please do not shorten "you" to "u". It can be hard to read and unfit for the level of formality Stack Overflow seeks. – Michael M. Apr 18 '23 at 17:51