【发布时间】:2016-05-04 14:52:15
【问题描述】:
我有一个使用 expressjs 的服务器设置,它使用 socket.io 与前端客户端通信。服务器在树莓派上运行,并提供了一个后端来使用 mplayer nodejs 模块为我的音乐库控制 mplayer 播放器。
大多数更新前端客户端的操作都是基于 mplayer EventEmitter 模块发出的事件。例如:
当以player.stop() 发出停止播放器的命令时,播放器的EventEmitter 实例会发出'stop' 事件。
然后服务器按如下方式侦听此事件:
player.on('stop', socket.emit('stop'));
我注意到的问题是,随着越来越多的客户端通过套接字 io 连接到服务器,每个客户端都会为 mplayer EventEmitter 'stop' 事件创建一个侦听器!因此,例如,如果有 3 个客户端,我会倾向于从玩家 EventEmitter 接收 3 个'stop' 事件,然后向我的前端客户端发送 3 个'stop' 事件。
我的问题是如何确保只为玩家事件创建一个侦听器?为什么每个客户端都将自己绑定为 EventEmitter 事件的侦听器?
我的服务器端 socketio 设置如下:
io.on('connection', function(socket) {
console.log('a user connected @ ' + socket.id);
///// Listen for player to successfully stop playing or when EOF is reached
player.on('stop', function() {
console.log("Received Stop Event From Player");
socket.emit('song:next'); //Play next song
}
3 个客户端连接时的控制台输出,接收到'stop' 事件:
Received Stop Event From Player
Received Stop Event From Player
Received Stop Event From Player
这导致我发送 3 个'next' 事件以发送给我的所有客户。
MPlayer nodejs 看起来像这样:
this.player.on('playstop', function() {
if(options.verbose) {
console.log('player.stop');
}
this.emit('stop')
}.bind(this));
通过 stackoverflow 进一步调查,它似乎类似于这个问题: Local eventEmitter listening to global eventEmitter
但是由于使用了 addListener 和 removeListener,cmets 中提供的解决方案对我没有意义?有人可以为我分解并解释我将如何实现其中提到的内容吗?
【问题讨论】:
-
您将需要实现一个 removeListener 函数,就像您提到的问题一样。但这只会在用户断开连接时调用。我还认为每个用户都需要一个特定的套接字事件。您可以为此使用
socket.id。因此,对于您发出和侦听的所有事件,您将在末尾附加socket.id。 -
如果玩家知道向它发送停止命令的套接字 id 会更有意义吗?这样,在玩家的
emit('stop')中,我可以将id 作为数据emit('stop', {id: clientId})发送,而服务器套接字将emit('next')仅用于该clientId? -
是的,这样会更有意义。您应该这样做,这样您就不必绑定所有这些事件。绑定一个事件 => 传递 id => 使用 id 执行用户特定的操作。 ??????????
-
非常感谢。我想我将使用一个 masterClientId 将下一个事件发送到前端。
标签: node.js sockets express eventemitter mplayer