Search code examples
javascriptnode.jssocketssocket.ioserversocket

socket.io the room in the rooms dictionary is 'undefined'?


so I'm emitting an event from my client that sends a string containing the socket/roomID I'm trying to connect to in it. When the data is received, it's handled by this code on the server side:

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;

app.use(express.static(__dirname + '/public'));

//runs when the user connects to the server
function onConnection(socket){
  console.log('a user connected');
  // socket.join('some room');
  console.log('Created Room: ' + socket.id);

  socket.emit("RoomID", socket.id);
  socket.on("location", (receivedString) => {
    // socket.emit("RoomID", socket.id);
    socket.to(socket.id).emit("redirectLocation", receivedString);
    console.log('\nReceived the following data from socket "' + socket.id + '": ' + receivedString);
    console.log('The amount of people in this room is ' + io.sockets.adapter.rooms.get(socket.id).size + '.');
  });

  //runs when the user is trying to join a specific room
  socket.on("joinRoom", (roomIdentifier) => {
    console.log('The room identifier is: ' + roomIdentifier);
    console.log('The room is already in the rooms array: ' + io.sockets.adapter.rooms[String(roomIdentifier)]);
    if (io.sockets.adapter.rooms[roomIdentifier]) {
    socket.join(roomIdentifier);
    } else {
      console.log(socket.id + 'tried to join ' + roomIdentifier + 'but the room does not exist.');
    };
  });
  socket.on('disconnect', onDisconnection);
}

//runs when the user disconnects from the server
function onDisconnection(socket){
  console.log('a user disconnected');
}

//runs when the socket manager registers a connection
io.on('connection', onConnection);

//Runs when a new room was created
io.of("/").adapter.on("create-room", (room) => {
  console.log(`room ${room} was created`);
});

io.of("/").adapter.on("join-room", (room, id) => {
  console.log(`socket ${id} has joined room ${room}`);
});

http.listen(port, () => console.log('listening on port ' + port));

I don't know why it's coming out as undefined--I thought maybe it was because the rooms dictionary wasn't supposed to have a string or something as a key but I'm really not sure.


Solution

  • There are two problems in the code shared:

    Check whether a room already exists

    The following command shows that io.sockets.adapter.rooms is a JavaScript Map object.

    console.log(io.sockets.adapter.rooms)
    // returns [object Map]
    

    To check whether the Map contains the room name, the Map.has(key) should then be used, instead of Map[key]:

    io.sockets.adapter.rooms.has(roomIdentifier)
    

    Once the room existence checks are adapted as above, the code still fails to let users join a room, as explained below.

    Joining a room

    The if statement lets the user join a room only if the room already exists, and does nothing otherwise. As a consequence, rooms are never created, and hence no user can ever join any of them.

    if (io.sockets.adapter.rooms.has(roomIdentifier)) {
      socket.join(roomIdentifier);
    } else {
      console.log(socket.id + 'tried to join ' + roomIdentifier + 'but the room does not exist.');
      // Socket.join is not executed, hence the room not created.
    };
    

    socket.join should be executed outside of the if statement. The if statement can probably be removed from the code, unless some specific action needs to be taken depending on it.

    if (io.sockets.adapter.rooms.has(roomIdentifier)) {
      // action when room already exists
    } else {
      console.log(socket.id + 'tried to join ' + roomIdentifier + 'but the room does not exist.');
      // action when room is new
    };
    
    // join the room in any case
    socket.join(roomIdentifier);