How to Get All Active Rooms with Users in Socket.io


I needed a way to get all rooms with users in Socket.io.

Suppose I’m running Socket.io on an Express server.

const socketio = require("socket.io");
const server = http.createServer(app);
const io = socketio(server);

Socket.io provides us with io.sockets.adapter.rooms, which is a mapping from all rooms to a set of socket IDs, or sids.

Suppose I have 2 rooms and 4 users, 2 in each room. This is what io.sockets.adapter.rooms would look like.

{
  '4ziBKG9XFS06NdtVAAAH': Set(1) {'4ziBKG9XFS06NdtVAAAH'},
  'room1':                Set(2) {'4ziBKG9XFS06NdtVAAAH', '7R9FawJDmTHxxgDkAAAJ'},
  '7R9FawJDmTHxxgDkAAAJ': Set(1) {'7R9FawJDmTHxxgDkAAAJ'},
  '4AGLhaRt96FlD6YiAAAL': Set(1) {'4AGLhaRt96FlD6YiAAAL'},
  'room2':                Set(2) {'4AGLhaRt96FlD6YiAAAL', 'g9wc5jWisESC9UlVAAAL'},
  'g9wc5jWisESC9UlVAAAL': Set(1) {'g9wc5jWisESC9UlVAAAL'}
}

You’ll notice that io.sockets.adapter.rooms also returns a mapping from every user sid to a set containing that exact same sid.

Clearly, we only want room1 and room2 from this map.

The only valid, active rooms are those whose key does not exist in the set of sids (e.g. room1 does not exist in io.sockets.adapter.rooms['room1'])

function getActiveRooms(io) {
    // Convert map into 2D list:
    // ==> [['4ziBKG9XFS06NdtVAAAH', Set(1)], ['room1', Set(2)], ...]
    const arr = Array.from(io.sockets.adapter.rooms);
    // Filter rooms whose name exist in set:
    // ==> [['room1', Set(2)], ['room2', Set(2)]]
    const filtered = arr.filter(room => !room[1].has(room[0]))
    // Return only the room name: 
    // ==> ['room1', 'room2']
    const res = filtered.map(i => i[0]);
    return res;
}