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;
}