web-dev-qa-db-ja.com

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;
56

Socket.io.jsのソースを見ると(ドキュメントにはありません)、次の2つの関数が見つかりました。

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

アプリでremoveAllListenersを正常に使用しました。これらから選択できるはずです:

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

また、cbProxy = _blankのソリューションが実際に機能するとは思いません。これは、実際のsocket.ioイベントではなく、cbProxy変数にのみ影響します。

74
Andrew Magee

一度だけ「聞く」リスナーを作成する場合は、socket.once('news',func)を使用します。 Socket.ioは、イベントが発生した後、リスナーを自動的に無効にします。これは「揮発性リスナー」と呼ばれます。

30
András Endre

Socket.io Client(1.4.8)の現在のバージョンのコードを見ると、offremoveAllListeners 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

22
Pjotr

Socket.ioバージョン0.9.16はremoveListenerを実装しますが、offは実装しません。

購読を解除するときは、removeListenerの代わりにoffを使用するか、次のようにoffを実装します。

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

Backbone listenToイベントサブスクリプションアプローチを使用している場合、イベントをサブスクライブ解除するときにBackboneがoffを呼び出すため、上記を実装する必要があります。

5
deedw

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;
    };
3
radiofrequency

クライアントのイベントリスナーを削除する

var Socket = io.connect();
Socket.removeListener('test', test);
1
Jijo Paulose

この作品を作るのに苦労した点があったので、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);
  }
1
Joshua Ohana

配列を使用してイベントを事前に保存し、サブスクライブを解除する必要があるまでに、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")
0
Raz

@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);
});
0
loonison101

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);
0
efkan