3 回答
TA贡献1874条经验 获得超12个赞
Socket.io 在最新版本中进行了一些重大更改,无法像以前一样访问房间。它将很多对象和数组更改为映射和集合,您可以在您发布的日志中看到它。
Set对象是值的集合。您可以按插入顺序迭代集合的元素。Set中的一个值只能出现一次;它在套装系列中是独一无二的。
该Map对象保存键值对并记住键的原始插入顺序。任何值(对象和原始值)都可以用作键或值。
访问映射的属性与访问普通对象的属性的方式不同。例子:
const myMap = new Map();
myMap.set("foo", "bar");
console.log(myMap["foo"]) // undefined
console.log(myMap.get("foo")) // bar
同样适用于集合,但是在您的情况下,特别查询此集合可能是错误的方法,因为此集合仅包含 id 的集合,而不是实际的房间对象。即使您要从 Set 中获取值,您也无法访问它的属性(主机、isOpen 和玩家),因为它只是一个字符串。
恐怕 3.0 版本使得直接访问所有房间列表变得不可能了。然而,适配器现在有一个属性socketRooms,可以用来代替它。
为了更容易地访问套接字的房间,您应该像这样访问它们:
io.sockets.adapter.socketRooms(socketId);
然而,这仍然只会返回一个字符串列表。
此问题最简单的解决方案是在连接范围之外创建一个外部变量。
const rooms = {};
io.on('connection', (socket, next) => {
socket.on('create game', async () => {
console.log('Creating game...');
socket.username = await generateUsername();
socket.roomId = generateId();
socket.join(socket.roomId);
if (!rooms[socket.roomId]) rooms[socket.roomId] = {};
rooms[socket.roomId].host = socket.username;
rooms[socket.roomId].isOpen = true;
rooms[socket.roomId].players = [socket.username];
console.log('Game created! ID: ', socket.roomId);
});
}
TA贡献1794条经验 获得超7个赞
在从 Socket.io 更改Array
为Map
. 一个简单的解决方案是改变:
io.sockets.adapter.rooms[socket.roomId].host = socket.username;
到:
io.sockets.adapter.get(socket.roomId).host = socket.username;
TA贡献1830条经验 获得超3个赞
正如您在自己的日志中看到的,io.sockets.adapter.rooms
是一个Map
对象(在socket.io的更高版本中),而不是一个普通对象。这意味着房间是通过 访问的.get()
,而不是通过简单的索引(例如您正在使用的索引)访问:
io.sockets.adapter.rooms[socket.roomId].host = socket.username;
这根本行不通,因为socket.roomId
地图上没有普通属性。
如果你想获取房间对象,你必须这样做:
let roomObj = io.sockets.adapter.rooms.get(socket.roomId); roomObj.host = socket.username;
在我看来,我不会直接弄乱房间里的物体。我们已经知道 socket.io 之前已经改变了他们的设计,将任何试图使用它们的代码渲染为损坏的并且需要重新设计。相反,我可能只是创建自己的数据结构,在其中存储自己的数据,然后我就不会依赖于 socket.io 如何改变其设计的突发奇想。直接访问房间对象不是socket.io 的承诺设计或承诺的API。他们可以随时改变它的工作方式,而且最近确实已经改变了它。
添加回答
举报