次のようなソケットサーバーにサブスクリプションを作成するオブジェクトがあるとします。
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のソースを見ると(ドキュメントにはありません)、次の2つの関数が見つかりました。
removeListener = function(name, fn)
removeAllListeners = function(name)
アプリでremoveAllListeners
を正常に使用しました。これらから選択できるはずです:
socket.removeListener("news", cbProxy);
socket.removeAllListeners("news");
また、cbProxy = _blank
のソリューションが実際に機能するとは思いません。これは、実際のsocket.ioイベントではなく、cbProxy
変数にのみ影響します。
一度だけ「聞く」リスナーを作成する場合は、socket.once('news',func)
を使用します。 Socket.ioは、イベントが発生した後、リスナーを自動的に無効にします。これは「揮発性リスナー」と呼ばれます。
Socket.io Client(1.4.8)の現在のバージョンのコードを見ると、off、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
Socket.ioバージョン0.9.16はremoveListener
を実装しますが、off
は実装しません。
購読を解除するときは、removeListener
の代わりにoff
を使用するか、次のようにoff
を実装します。
var socket = io.connect(url);
socket.off = socket.removeListener;
Backbone listenTo
イベントサブスクリプションアプローチを使用している場合、イベントをサブスクライブ解除するときにBackboneがoff
を呼び出すため、上記を実装する必要があります。
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);
この作品を作るのに苦労した点があったので、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);
}
配列を使用してイベントを事前に保存し、サブスクライブを解除する必要があるまでに、offメソッドを使用します。これは、socket.ioの組み込みメソッドです。
// init
var events = []
// store
events.Push("eventName")
// subscribe
socket.on("eventName", cb)
// remove
events = events.filter(event => event!="eventName")
// unsubscribe
socket.off("eventName")
@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);