Socket.io socket.rooms 返回空

Socket.io socket.rooms is returned empty

我已经编写了一个简单的 Socket.io 后端,现在正在尝试检查套接字是否已经加入房间。

根据文档:

socket.rooms

应该return 套接字加入的房间列表。但是,对我来说这似乎总是一个空数组。

下面是我的服务器端演示问题的快速示例代码:

const express = require('express');
const app = express();
const http = require('http');
const https = require('https');
const fs = require('fs');
require('dotenv').config();

function isJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

function relayMessage(room_id,msg){
    io.to(room_id).emit('chat message', msg);   
    console.log('Relay msg to room: ' + room_id);
}

function joinRoomAndMessage(room_id,socket,msg){
    //Join the room.
    socket.join(room_id);
    console.log('Joined Room: ' + room_id);
    
    //Relay the first message.
    relayMessage(room_id,msg);
}

//Create the server.
var server = null;
if(process.env.SSL_KEY_FILE.length>0){
    //If the key file is defined in .env, try to start the server in https mode.
    
    const options = {
      key: fs.readFileSync(process.env.SSL_KEY_FILE),
      cert: fs.readFileSync(process.env.SSL_CERT_FILE)
    };
    
    server = https.createServer(options, app);
    console.log('Starting server in HTTPS mode');
}else{
    //If the key file is not defined in .env, start the server in http mode.
    server = http.createServer(app);
    console.log('Starting server in HTTP mode');
}
const { Server } = require("socket.io");
const io = new Server(server);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {

  console.log('a user connected');
  socket.on('disconnect', () => {
console.log('user disconnected');


 });



socket.on('chat message', (msg) => {
  
console.log('message: ' + msg);
// Always expect JSON messages.
if(isJsonString(msg)){
    const msgJSON = JSON.parse(msg);
    // Always expect the JSON to have a room_id.
    if(msgJSON.room_id){
        
        console.log("LIST OF ROOMS:"+JSON.stringify(socket.rooms));
        
        if(!Object.keys(socket.rooms).includes(msgJSON.room_id)){
            
            joinRoomAndMessage(msgJSON.room_id,socket,msg);
            
        }else {
            relayMessage(msgJSON.room_id,msg);
        }
    }else{
        console.log('No relay. The server is expecting a room_id.');
    }
}else{
    console.log('No relay. The server is expecting JSON message.');
}
  });
  
});

// use port 3000 unless there exists a preconfigured port
const port = process.env.PORT || 3000;

server.listen(port, () => {
    console.log('listening on *:'+port);
});

此外,下面是一个控制台日志,当我使用上面的代码将三个消息推送到同一个套接字时:

Starting server in HTTPS mode
listening on *:3000
a user connected
user disconnected
a user connected
message:  {"room_id":"12345","msg":"Test message"}
LIST OF ROOMS:{}
Joined Room: 12345
Relay msg to room: 12345
message:  {"room_id":"12345","msg":"Test message 2"}
LIST OF ROOMS:{}
Joined Room: 12345
Relay msg to room: 12345
message:  {"room_id":"12345","msg":"Test message 3"}
LIST OF ROOMS:{}
Joined Room: 12345
Relay msg to room: 12345 

有没有人知道为什么数组是空的或者有其他方法可以检查插座当前在哪个房间?

此致,

奥利

P.S。这个 post (socket.rooms returns empty array) 提到我可能必须在填充 socket.rooms 之前等待,但是在将下一条消息发送到已经打开的套接字时我仍然得到一个空数组加入了房间,因此我认为我的问题一定是其他问题。

服务器端的

socket.rooms 是一个 Set 对象。您需要使用正确的方法来访问它并记录它。

例如:

console.log(JSON.stringify(socket.rooms))

不会在其中显示任何内容,因为 Set 上没有可枚举的属性,而这正是 JSON.stringify() 所寻找的。

相反,这样做:

console.log("LIST OF ROOMS:", socket.rooms);

console.log直接将其视为一个集合并输出它的项目。


还有这个:

 if(!Object.keys(socket.rooms).includes(msgJSON.room_id))

在 Set 对象上做有点疯狂。你应该这样做:

 if (!socket.rooms.has(msgJSON.room_id))

并使用 Set 对象的内置功能(这就是它的用途)。

实际上,您甚至不必检查它,因为您总是可以 .join() 因为它不会对 .join() 您已经使用的东西造成任何问题。所以, 每次加入然后发送消息即可。