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。他們可以隨時改變它的工作方式,而且最近確實已經改變了它。
添加回答
舉報