我想知道是否有聪明的人可以告诉我如何在 OOP 环境中使用 ES6 类实现 Socket.IO。我在使用 Socket.io 时遇到的主要问题是传递服务器对象,在我的例子中称为“io”。我见过的几乎每个 socket.io 示例都是纯粹的意大利面条式代码,一个文件包含许多与套接字相关的事件和逻辑。首先,我尝试将服务器对象 io 传递给新类的构造函数,但由于某种原因,您最终会收到令人讨厌的“RangeError:超出最大调用堆栈大小”错误消息。然后我尝试将我的类包装在 module.exports 函数中,该函数的参数应包含 io 对象。对于头等舱来说这很好。假设我将 io 对象传递到我的游戏中,效果如预期的那样出色。但是当我尝试将 io 对象引用到 Round 类时(Game 包含 Rounds 数组),我不能这样做。因为这是 NodeJS 中一种糟糕的做法,所以 require 应该是全局的,而不是在模块/函数内部。所以我再次遇到同样的问题。
app.js(我需要主套接字文件)
const io = socketio(server, { origins: '*:*' });
...
require('./sockets')(io);
sockets/index.js(我在其中初始化游戏服务器,并处理来自客户端套接字的传入消息)
const actions = require('../actions.js');
const chatSockets = require('./chat-sockets');
const climbServer = require('./climb-server');
const authFunctions = require('../auth-functions');
module.exports = (io) => {
io.on('connection', (client) => {
console.log('client connected...');
// Standard join, verify the requested room; if it exists let the client join it.
client.on('join', (data) => {
console.log(data);
console.log(`User ${data.username} tries to join ${data.room}`);
console.log(`Client joined ${data.room}`);
client.join(data.room);
});
client.on('disconnect', () => {
console.log('Client disconnected');
});
client.on(actions.CREATE_GAME, (hostParticipant) => {
console.log('CREATE_GAME', hostParticipant);
// Authorize socket sender by token?
// Create a new game, and set the host to the host participant
climbServer.createGame(io, hostParticipant);
});
client.on(actions.JOIN_GAME, (tokenizedGameId) => {
console.log('JOIN_GAME');
const user = authFunctions.getPayload(tokenizedGameId.token);
// Authorize socket sender by token?
// Create a new game, and set the host to the host participant
const game = climbServer.findGame(tokenizedGameId.content);
game.joinGame(user);
});
});
};
climbServer.js(我的游戏服务器,用于跟踪事件游戏)
const actions = require('../actions.js');
const Game = require('../models/game');
const climbServer = { games: { }, gameCount: 0 };
climbServer.createGame = (io, hostParticipant) => {
// Create a new game instance
const newGame = new Game(hostParticipant);
console.log('New game object created', newGame);
// Store it in the list of game
climbServer.games[newGame.id] = newGame;
// Keep track
climbServer.gameCount += 1;
// Notify clients that a new game was created
io.sockets.in('climb').emit(actions.CLIMB_GAME_CREATED, newGame);
};
climbServer.findGame = gameId => climbServer.games[gameId];
module.exports = climbServer;
Game.js(应该能够向所有连接的套接字发出信号的 ES6 类)
const UUID = require('uuid');
const Round = require('./round');
class Game {
// Constructor
constructor(hostParticipant) {
this.id = UUID();
this.playerHost = hostParticipant;
this.playerClient = null;
this.playerCount = 1;
this.rounds = [];
this.timestamp = Date.now();
}
joinGame(clientParticipant) {
console.log('Joining game', clientParticipant);
this.playerClient = clientParticipant;
this.playerCount += 1;
// Start the game by creating the first round
return this.createRound();
}
createRound() {
console.log('Creating new round at Game: ', this.id);
const newRound = new Round(this.id);
return this.rounds.push(newRound);
}
}
module.exports = Game;
Round.js(Game类使用的ES6类(存储在rounds数组中))
const actions = require('../actions.js');
class Round {
constructor(gameId) {
console.log('Initializing round of gameId', gameId);
this.timeLeft = 60;
this.gameId = gameId;
this.winner = null;
this.timestamp = Date.now();
// Start countdown when class is instantiated
this.startCountdown();
}
startCountdown() {
const countdown = setInterval(() => {
// broadcast to every client
io.sockets.in(this.gameId).emit(actions.ROUND_TIMER, { gameId: this.gameId, timeLeft: this.timeLeft });
if (this.timeLeft === 0) {
// when no time left, stop counting down
clearInterval(countdown);
this.onRoundEnd();
} else {
// Countdown
this.timeLeft -= 1;
console.log('Countdown', this.timeLeft);
}
}, 1000);
}
onRoundEnd() {
// Evaluate who won
console.log('onRoundEnd: ', this.gameId);
}
}
module.exports = Round;
总结一个问题:如何将 io 的引用传递给我的类,以便我能够向这些类中连接的套接字发出信号? 这不一定是 ES6 类,它可以是使用 .prototype 属性的 NodeJS 对象。我只是想要一种可维护的方式来使用套接字处理我的游戏服务器...感谢任何帮助!
最佳答案
经过几个小时的努力,我找到了一个解决方案。如果有人遇到同样的事情,请查看下面我的解决方案。不是最好的,但比将所有套接字相关代码放在一个文件中要好得多......
Game.js(ES6 类)。关注包含“module.exports”的第一行。
const GameFactory = require('../models/game');
const climbServer = { games: { }, gameCount: 0 };
climbServer.createGame = (io, hostParticipant) => {
// Create a new game instance
const Game = GameFactory(io);
const newGame = new Game(hostParticipant);
console.log('New game object created', newGame);
// Store it in the list of game
climbServer.games[newGame.id] = newGame;
// Keep track
climbServer.gameCount += 1;
return newGame;
};
climbServer.findGame = gameId => climbServer.games[gameId];
module.exports = climbServer;
诀窍是在您首先声明的地方使用此工厂模式:
const GameFactory = require('../models/game');
然后通过传入 Socket.io 服务器对象(在我的例子中为“io”)来初始化工厂。如果您通过构造函数传递它,您最终会得到 RangeError,因此这是唯一的方法。再次不确定此代码与意大利面条代码相比的性能如何。
const Game = GameFactory(io);
最后,您现在可以实例化类的实例:
const newGame = new Game(hostParticipant);
如果有人有改进或想法,请给我留言。仍然不确定这段代码的质量。
关于javascript - Socket.io 在 ES6 类中发出值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47341491/