如何使用socket.io在多个模块中定义侦听器

时间:2014-06-04 15:12:24

标签: javascript node.js socket.io

半年前,我在node.js和socket.io中编写了一个小型多人游戏。现在我试图改进它,我的一个改进是将代码分解成模块(顺便说一下。我使用expressjs 4.4和socket.io 1.0)。我有一个玩家队列来处理连接玩家的顺序。一切都很顺利,直到我遇到socket.io:我想在播放器队列中处理(dis-)连接监听器,而我想把所有与游戏相关的监听器放在我的游戏模块中。我尝试了一些事情,包括Using socket.io from a moduleWhat's the correct way to pass a Socket.IO socket between modules?,我没有把它带到工作中。目前我正在传递io对象:

io = require("socket.io")(server);

我错过了什么吗?

我的代码:

PlayerManager.js

var log = require("npmlog"),
    Player = require("./Model/Player").Player;

var playerIo;

var PlayerManager = (function() {
    var self;

    function PlayerManager(eventEmitter, io) {
        log.info("PlayerManager", "loading PlayerManager");

        self = this;

        this.eventEmitter = eventEmitter;
        this.io = io;
        this.playerQueue = [];
        this.players = [];

        this.setSocketListeners();
    }

    PlayerManager.prototype.setSocketListeners = function() {
        log.info("PlayerManager", "loading SocketListeners");

        playerIo = this.io.of("/player").on("connection", function(socket) {
            log.info("PlayerManager", "Player " + socket.id + " has connected");

            socket.on("disconnect", function() {
                log.info("PlayerManager", "Player " + socket.id + " has disconnected.");

                self.removePlayer(socket.id);
            });

            self.addPlayer(new Player(socket));
        });
    };

    PlayerManager.prototype.addPlayer = function(player) {
        log.info("PlayerManager", "Pushing Player " + player.socket.id + " to Queue. Current position: " + this.playerQueue.length);

        this.playerQueue.push(player);
    };

    PlayerManager.prototype.removePlayer = function(id) {
        log.info("PlayerManager", "Removing Player " + id + " from Queue");

        var player = this.getPlayerById(id);

        if (!player) {
            return;
        }

        this.playerQueue.splice(this.playerQueue.indexOf(player), 1);
    };

    PlayerManager.prototype.getPlayers = function() {
        log.info("PlayerManager", "Choosing players (length of queue: " + this.playerQueue.length + ")");

        this.players = [];

        if (this.playerQueue.length >= 1) { //should be changed to 2 in PROD
            var player;

            for (var i = 0; i < 4; ++i) {
                player = this.playerQueue.shift();

                if (player !== undefined && !player.socket.disconnected) {
                    player.socket.join("players");
                    this.players.push(player);
                }
            }

            return this.players;
        } else {
            return false;
        }
    };

    PlayerManager.prototype.onGameFinished = function() {
        var player;

        while (this.players && this.players.length > 0) {
            player = this.players.shift();

            player.socket.leave("players");

            log.info("GameManager", "players size: " + self.players.length);
        }
    };

    PlayerManager.prototype.getPlayerById = function(id) {
        for (var i = 0; i < this.playerQueue.length; ++i) {
            if (this.playerQueue[i].socket.id === id) {
                return this.playerQueue[i];
            }
        }

        return false;
    };

    return PlayerManager;
})();

exports = module.exports = PlayerManager;

Game.js

var log = require("npmlog");
var config = require("./config");
var Duck = require("./Model/Duck").Duck;

var Game = (function() {
    var self;

    function Game(eventEmitter, io, players) {
        log.info("Game", "loading ...");

        self = this;

        this.io = io;
        this.eventEmitter = eventEmitter;
        this.players = players;

        setInterval(function() {
            self.io.to("players").emit("blub");
        });

        // ...

    return Game;
})();

exports = module.exports = Game;

并且为了完整性:

index.js (客户端)

define(["socketio"], function(io) {
    var socket = io("/player");

    socket.on("blub", function() {
        console.log("blub");
    });

    setInterval(function() {
        socket.emit("blub");
    }, 1000);
});

1 个答案:

答案 0 :(得分:0)

一年之后,我有时间清理并分享我在那段时间内获得的见解。

在整个项目中传播与socket.io相关的代码是糟糕的设计(或者来自任何其他库的代码)。如果您必须更改包装器库,则必须在代码库中的许多位置执行此操作。更好的方法是将socket.io的使用限制在一个薄层,在该薄层中完成与websockets之间的所有通信。从那以后,您将使用另一层消息:您自己的消息。 Node.js的&#39;自己的EventEmitter是你工作所需要的一切。