如何取消订阅 socket.io 订阅?

IT技术 javascript socket.io publish-subscribe
2021-03-18 22:48:07

假设有对象订阅套接字服务器,如下所示:

socket.on('news', obj.socketEvent)

这些对象的生命周期很短并且经常被创建,从而产生许多订阅。这似乎是内存泄漏和容易出错的情况,可以通过这种方式直观地防止:

socket.off('news', obj.socketEvent)

在对象被删除之前,但是,off套接字中没有方法。是否有另一种方法用于此目的?

编辑:没有找到答案,我正在分配一个空白方法来覆盖原始事件处理程序的包装方法,下面是一个示例。

var _blank = function(){};

var cbProxy = function(){
    obj.socketEvent.apply(obj, arguments)
};
var cbProxyProxy = function(){
    cbProxy.apply ({}, arguments)
}
socket.on('news', cbProxyProxy);

// ...and to unsubscribe 
cbProxy = _blank;
6个回答

通过查看socket.io.js的源代码(在任何地方的文档中都找不到),我发现了这两个函数:

removeListener = function(name, fn)
removeAllListeners = function(name)

removeAllListeners在我的应用程序中成功使用您应该可以从以下选项中进行选择:

socket.removeListener("news", cbProxy);
socket.removeAllListeners("news");

另外,我认为您的解决方案cbProxy = _blank实际上行不通;这只会影响cbProxy变量,不会影响任何实际的 socket.io 事件。

这似乎有效,该事件从 SocketNamespace 消失了,尽管我还没有对这部分进行广泛的测试。此外,您对代理解决方案的看法是正确的,因此更新了它的幽默感
2021-04-21 22:48:07
什么不起作用?cbProxy是 OP 定义的回调方法。
2021-05-13 22:48:07

如果要创建仅“侦听”一次的侦听器,请使用socket.once('news',func). Socket.io 会在事件发生后自动销毁监听器——它被称为“易失性监听器”。

查看当前版本的 Socket.io Client (1.4.8) 的代码,似乎offremoveAllListenersremoveEventListener都指向同一个函数。

调用其中任何一个,提供事件名称和/或回调,都会得到所需的结果。根本不提供任何东西似乎会重置一切。

请务必谨慎对待fn/callback参数。它必须与代码中使用的实例相同。

例子:

var eventCallback = function(data) {
  // do something nice
};
socket.off('eventName', eventCallback);

会按预期工作。

示例(也将起作用):

function eventCallback(data) {
  // do something nice
}
socket.off('eventName', eventCallback);

请注意,您尝试删除的回调是您传入的回调(这个回调会带来很多混乱和挫折)。此示例实现了初始回调的包装器,试图删除它,因为添加的真正回调是一个未公开的闭包实例:http : //www.html5rocks.com/en/tutorials/frameworks/angular-websockets/

这是代码库中该特定行的链接:https : //github.com/socketio/socket.io-client/blob/master/socket.io.js#L1597

如果您使用的是socket.io-clientnpm 包,那么这效果最好,因为它removeAllListeners()是无参数的(因此您无法指定eventName)。
2021-04-30 22:48:07
这个答案需要更多的赞成,因为大多数其他答案都不完整和/或非常过时。
2021-05-06 22:48:07
off 的回调都不会触发,如果给出回调,则 off 不会起作用。
2021-05-10 22:48:07
链接到此处的文档
2021-05-13 22:48:07

Socket.io 0.9.16 版实现了,removeListener但没有实现off

您可以在取消订阅时使用removeListener代替off,或者简单地实现off如下:

  var socket = io.connect(url);
  socket.off = socket.removeListener;

如果您使用 BackbonelistenTo事件订阅方法,则需要off在取消订阅事件时将上述内容实现为 Backbone 调用

我发现在 socket.io 0.9.11 和 Chrome24 socket.io removeListener 中不起作用。

这个修改后的版本对我有用:

EventEmitter.prototype.removeListener = function (name, fn) {
        if (this.$events && this.$events[name]) {
            var list = this.$events[name];

            if (io.util.isArray(list)) {
                var pos = -1;

                for (var i = 0, l = list.length; i < l; i++) {
                    if (list[i].toString() === fn.toString() || (list[i].listener && list[i].listener === fn)) {
                        pos = i;
                        break;
                    }
                }

                if (pos < 0) {
                    return this;
                }

                list.splice(pos, 1);

                if (!list.length) {
                    delete this.$events[name];
                }
            } else  {
                    if (list.toString() === fn.toString() || (list.listener && list.listener === fn)) {

                       delete this.$events[name];
                    }
            }
        }

        return this;
    };