如何取消订阅socket.io订阅?
假设有一些对象订阅套接字服务器,如下所示:
socket.on('news', obj.socketEvent)
这些对象的寿命很短,而且经常创build,产生了很多订阅。 这看起来像是一个内存泄漏和一个容易出错的情况,这种情况会直接被阻止:
socket.off('news', obj.socketEvent)
在删除对象之前,可惜的是,socket中没有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;
从查看socket.io.js的源文件(无法在任何地方find它),我发现了这两个函数:
removeListener = function(name, fn) removeAllListeners = function(name)
我在我的应用程序中成功地使用了removeAllListeners
; 你应该可以从这些select:
socket.removeListener("news", cbProxy); socket.removeAllListeners("news");
另外,我不认为你的解决schemecbProxy = _blank
会实际上工作; 这只会影响cbProxy
variables,而不会影响任何实际的socket.io事件。
如果你想创build只监听一次使用socket.once('news',func)
侦听器。 事件发生后,Socket.io会自动破坏监听器 – 它被称为“volatile listener”。
看一下当前版本的Socket.io Client(1.4.8)的代码,好像closures了 , removeAllListeners , removeEventListener都是指向相同的函数。
调用其中的任何一个,提供事件名称和/或callback,给出所需的结果。 根本不提供任何东西似乎重置了一切。
请谨慎对待fn / callback参数。 它必须与代码中使用的实例相同。
例:
var eventCallback = function(data) { // do something nice }; socket.off('eventName', eventCallback);
会按预期工作。
例子(也将工作):
function eventCallback(data) { // do something nice } socket.off('eventName', eventCallback);
请谨慎,您尝试删除的callback是您通过的callback(这可能会带来很多混乱和挫折)。 这个例子实现了一个初始callback的包装,试图删除那不起作用的真正的callback被添加是一个未公开的闭包实例: http : //www.html5rocks.com/en/tutorials/frameworks/angular-websockets/
以下是代码库中特定行的链接: https : //github.com/socketio/socket.io-client/blob/master/socket.io.js#L1597
Socket.io 0.9.16版本实现了removeListener
但是没有off
。
您可以在取消订阅时使用removeListener
而不是off
,或者直接执行,如下所示:
var socket = io.connect(url); socket.off = socket.removeListener;
如果您使用Backbone listenTo
事件订阅方法,则需要在取消订阅事件时将上述内容实现为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; };
删除客户端上的事件侦听器
var Socket = io.connect(); Socket.removeListener('test', test);
要添加到@Andrew Magee,这里是一个在Angular JS中取消订阅socket.io事件的例子,当然也可以使用Vanilla JS:
function handleCarStarted ( data ) { // Do stuff } function handleCarStopped ( data ) { // Do stuff }
听事件:
var io = $window.io(); // Probably put this in a factory, not controller instantiation io.on('car.started', handleCarStarted); io.on('car.stopped', handleCarStopped); $scope.$on('$destroy', function () { io.removeListener('car.started', handleCarStarted); io.removeListener('car.stopped', handleCarStopped); });
同样在java
客户端上,可以用Javascript客户端以相同的方式完成。 我从socket.io粘贴。
// remove all listeners of the connect event socket.off(Socket.EVENT_CONNECT); listener = new Emitter.Listener() { ... }; socket.on(Socket.EVENT_CONNECT, listener); // remove the specified listener socket.off(Socket.EVENT_CONNECT, listener);
由于我有一个麻烦点使这个工作计算,我会在这里以及一个很好的更新的答案在2017年。感谢@Pjotr指出它必须是相同的callback实例。
在socket-io.subscriber服务中使用Angular2 TypeScript的示例。 请注意“newCallback”包装
private subscriptions: Array<{ key: string, callback: Function }>; constructor() { this.subscriptions = []; } subscribe(key: string, callback: Function) { let newCallback = (response) => callback(response); this.socket.on(key, newCallback); return this.subscriptions.push({key: key, callback: newCallback}) - 1; } unsubscribe(i: number) { this.socket.removeListener(this.subscriptions[i].key, this.subscriptions[i].callback); }