【问题标题】:Remove all event listeners except for specific ones in Socket.io删除除 Socket.io 中的特定事件侦听器之外的所有事件侦听器
【发布时间】:2013-04-28 23:22:31
【问题描述】:

我有带有 socket.io 的 node.js 应用程序,我用它来实时选择和加载不同的外部模块(我称之为“活动”)。

由于每个模块都将它自己的事件绑定到套接字,所以当我从一个模块更改为另一个模块时,我希望能够从我的套接字中删除前一个模块添加的所有事件侦听器。

我会使用emitter.removeAllListeners(),但这也会删除我在服务器中定义的事件,这是我不想要的。

我的代码如下所示:

app.js

// Boilerplate and some other code

var currentActivity;
io.sockets.on('connection', function(client){

    client.on('event1', callback1);
    client.on('event2', callback2);

    client.on('changeActivity', function(activityPath){
        var Activity = require(activityPath);
        currentActivity = new Activity();

        // Here I'd like some loop over all clients and:
        // 1.- Remove all event listeners added by the previous activity
        // 2.- Call currentActivity.bind(aClient) for each client
    });
})

示例活动如下所示

someActivity.js

module.exports = function(){

    // some logic and/or attributes

    var bind = function(client){

        client.on('act1' , function(params1){ // some logic
        });
        client.on('act2' , function(params2){ // some logic
        });
        // etc.
    }
}

因此,例如在此示例中,如果我从 someActivity.js 更改为其他活动,我希望能够为所有客户端删除“act1”和“act2”的侦听器,而不删除那些对于“event1”、“event2”和“changeActivity”。

你知道如何做到这一点吗?

【问题讨论】:

  • 您可以 (a) 通过侦听 newListener 事件来保留这些事件名称的列表,或者可能 (b) 使用 emitter.listeners() 获取您想要保留的事件的侦听器您想要保留的事件,清除所有其他内容,然后重新附加它们(从未尝试过,可能有副作用)。
  • @Wrikken,似乎没有 newListener 事件,或者至少我在文档中找不到它。有链接吗?对于您的第二个选项,我想我需要在服务器中知道模块中事件的名称,从而导致不希望的耦合。
  • 好吧,this page says there is。根据this page 的说法,它自 2009.08.27 版本 0.1.7 以来一直存在。
  • 抱歉,我正在查看 Socket.io 文档。谢谢;)

标签: javascript node.js socket.io


【解决方案1】:

我会在每个模块中创建一个名为 unbind 的方法,该方法会删除 bind 函数添加的所有侦听器:

var fun1 = function(params1){ // some logic };    
var fun2 = function(params2){ // some logic };

module.exports = function(){    
    // some logic and/or attributes    
    var bind = function(client){    
        client.on('act1' , fun1);
        client.on('act2' , fun2);
    }

    var unbind = function(client){
        client.removeEventListener('act1',fun1);
        client.removeEventListener('act2',fun2);
    };
};

如果您需要访问侦听器中的 客户端,我会对其进行重构以将客户端传递给构造函数:

function MyModule(client){
   this.client = client;
};
MyModule.prototype.fun1 = function(params1){
   //do something with this.client
};
MyModule.prototype.fun2 = function(params2){
   //do something with this.client
};
MyModule.prototype.bind = function(){
   this.client.on('act1' , this.fun1);
   this.client.on('act2' , this.fun2);
};
MyModule.prototype.unbind = function(){
   this.client.removeEventListener('act1' , this.fun1);
   this.client.removeEventListener('act2' , this.fun2);
};
module.exports = MyModule;

然后你可以像这样使用它:

client.on('changeActivity', function(activityPath){
    var Activity = require(activityPath);
    var currentActivity = activityCache[activityPath] || new Activity(client); //use the existing activity or create if needed
    previousActivity.unbind();
    currentActivity.bind();
});

【讨论】:

  • 谢谢。我曾想过一些东西作为第一个想法,但这对我来说似乎有点重复。另外,这取决于模块的实现,您认为还有另一种方法可以解决这个问题,即服务器可以控制解除绑定,而无需知道模块中事件的名称?
  • 另外,我认为你的重构会很好,但在我的情况下不是,因为我只想为所有 n 个客户端拥有一个模块实例。
  • 服务器只需要使用绑定和取消绑定方法,就像一个接口。我更改了用法以共享活动实例。我可能误解了你的意图。你能展示一些示例 socket.io 代码吗?
猜你喜欢
  • 2018-09-04
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 2022-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
相关资源
最近更新 更多