如何取消订阅socket.io订阅?
假设有制作订阅套接字服务器,像这样的对象:如何取消订阅socket.io订阅?
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;
通过观察socket.io.js源(无法找到它在任何地方的文件),我发现这两个函数:
removeListener = function(name, fn)
removeAllListeners = function(name)
我在我的应用程序使用removeAllListeners
成功;你应该能够从这些选择:
socket.removeListener("news", cbProxy);
socket.removeAllListeners("news");
另外,我不认为你的cbProxy = _blank
解决方案将实际工作;那只会影响cbProxy
变量,而不会影响任何实际的socket.io事件。
我发现在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;
};
如果你想创建的听众说,“听”只有一次使用socket.once('news',func)
。事件发生后,Socket.io会自动破坏侦听器 - 它被称为“volatile listener”。
Socket.io 0.9.16版本实施removeListener
而不是off
。
退订时,您可以使用removeListener
代替off
,或者干脆直接off
如下:
var socket = io.connect(url);
socket.off = socket.removeListener;
如果您使用的是骨干listenTo
事件订阅方法,您需要实现上述为骨架的电话off
取消订阅事件时。
客户
var Socket = io.connect();
Socket.removeListener('test', test);
为了增加@Andrew马吉的删除事件侦听器,这里是退订插座的一个例子。IO事件角JS,当然与香草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。在Socket.io客户端(1.4.8)的最新版本的代码
// 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);
展望似乎关闭,removeAllListeners,removeEventListener都指向相同的功能。
调用其中的任何一个,提供事件名称和/或回调,都会给出所需的结果。根本没有提供任何东西似乎重置了一切。
请谨慎对待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
这个答案需要更多upvotes,因为大多数其他的不完整和/或极端过时。 – 2016-10-28 21:37:56
由于我有一个麻烦点使这项工作计算,我会在这里以及一个很好的更新的答案2017年。感谢@Pjotr指出它必须是相同的回调实例。
在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);
}
这似乎工作,事件从SocketNamespace消失,虽然我还没有做这方面的广泛测试。你也是对的代理解决方案,所以它的更新为它的幽默 – 2012-03-14 14:47:18
这不工作? WTF cbProxy是? – 2015-08-06 14:55:30
什么不起作用? 'cbProxy'是OP定义的回调方法。 – 2015-08-11 03:04:58