2012-02-23 332 views
48

假設有製作訂閱套接字服務器,像這樣的對象:如何取消訂閱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; 

回答

69

通過觀察socket.io.js源(無法找到它在任何地方的文件),我發現這兩個函數:

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

我在我的應用程序使用removeAllListeners成功;你應該能夠從這些選擇:

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

另外,我不認爲你的cbProxy = _blank解決方案將實際工作;那隻會影響cbProxy變量,而不會影響任何實際的socket.io事件。

+0

這似乎工作,事件從SocketNamespace消失,雖然我還沒有做這方面的廣泛測試。你也是對的代理解決方案,所以它的更新爲它的幽默 – 2012-03-14 14:47:18

+0

這不工作? WTF cbProxy是? – 2015-08-06 14:55:30

+1

什麼不起作用? 'cbProxy'是OP定義的回調方法。 – 2015-08-11 03:04:58

3

我發現在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; 
    }; 
26

如果你想創建的聽衆說,「聽」只有一次使用socket.once('news',func)。事件發生後,Socket.io會自動破壞偵聽器 - 它被稱爲「volatile listener」。

5

Socket.io 0.9.16版本實施removeListener而不是off

退訂時,您可以使用removeListener代替off,或者乾脆直接off如下:

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

如果您使用的是骨幹listenTo事件訂閱方法,您需要實現上述爲骨架的電話off取消訂閱事件時。

1

客戶

var Socket = io.connect(); 
Socket.removeListener('test', test); 
0

爲了增加@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); 
}); 
0

而且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); 
12

展望似乎關閉removeAllListenersremoveEventListener都指向相同的功能。

調用其中的任何一個,提供事件名稱和/或回調,都會給出所需的結果。根本沒有提供任何東西似乎重置了一切。

請謹慎對待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

+1

這個答案需要更多upvotes,因爲大多數其他的不完整和/或極端過時。 – 2016-10-28 21:37:56

1

由於我有一個麻煩點使這項工作計算,我會在這裏以及一個很好的更新的答案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); 
    }