2012-02-23 38 views
48

Giả sử có những đối tượng làm thuê bao đến một máy chủ ổ cắm như vậy:Làm cách nào để hủy đăng ký thuê bao socket.io?

socket.on('news', obj.socketEvent)

Những đối tượng có tuổi thọ ngắn và thường xuyên được tạo ra, tạo ra nhiều thuê bao. Điều này có vẻ giống như một rò rỉ bộ nhớ và một tình huống dễ bị lỗi đó bằng trực giác sẽ được ngăn chặn theo cách này:

socket.off('news', obj.socketEvent)

trước khi đối tượng bị xóa, nhưng than ôi, không có một phương pháp off trong ổ cắm. Có phương pháp khác có nghĩa là cho điều này?

Chỉnh sửa: không tìm thấy câu trả lời Tôi chỉ định phương thức trống để ghi đè phương pháp trình bao bọc cho trình xử lý sự kiện ban đầu, ví dụ sau.

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; 

Trả lời

69

Từ nhìn vào nguồn gốc của socket.io.js (không thể tìm thấy nó trong tài liệu bất cứ nơi nào), tôi thấy hai chức năng:

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

tôi đã sử dụng removeAllListeners thành công trong ứng dụng của tôi; bạn sẽ có thể để lựa chọn sau đây:

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

Ngoài ra, tôi không nghĩ rằng giải pháp của bạn của cbProxy = _blank thực sự sẽ làm việc; điều đó sẽ chỉ ảnh hưởng đến biến số cbProxy, không ảnh hưởng đến bất kỳ sự kiện socket.io thực tế nào.

+0

Điều đó dường như hoạt động, sự kiện biến mất khỏi SocketNamespace mặc dù tôi chưa thực hiện thử nghiệm rộng rãi về phần này. Ngoài ra bạn đã đúng về các giải pháp proxy, do đó, nó được cập nhật cho sự hài hước của nó –

+0

Điều này không hoạt động? WTF cbProxy là gì? –

+1

Điều gì không hoạt động? 'cbProxy' là một phương thức gọi lại được định nghĩa bởi OP. –

3

Tôi thấy rằng trong socket.io 0.9.11 và Chrome24 socket.io removeListener không hoạt động.

phiên bản sửa đổi này làm việc cho tôi:

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

Nếu bạn muốn tạo người nghe rằng "lắng nghe" chỉ một lần sử dụng socket.once('news',func). Socket.io tự động sẽ làm phân tán người nghe sau khi sự kiện xảy ra - nó được gọi là "người nghe dễ bay hơi".

5

Socket.io phiên bản 0.9.16 triển khai removeListener nhưng không off.

Bạn có thể sử dụng thay vì removeListeneroff khi hủy đăng ký, hoặc đơn giản là thực hiện off như sau:

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

Nếu bạn đang sử dụng Backbone listenTo kiện tiếp cận đăng ký, bạn cần phải thực hiện ở trên như các cuộc gọi Backbone off khi hủy đăng ký sự kiện.

1

Loại bỏ một người biết lắng nghe sự kiện trên máy khách

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

Để thêm vào @ Andrew Magee, đây là một ví dụ về cách hủy đăng ký socket.sự kiện io trong góc JS, và tất nhiên làm việc với Vanilla JS:

function handleCarStarted (data) { // Do stuff } 
function handleCarStopped (data) { // Do stuff } 

Nghe cho các sự kiện:

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

Cũng trong ngày java khách hàng, nó có thể được thực hiện theo cùng một cách với khách hàng Javascript. Tôi đã dán từ 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); 
12

Nhìn vào mã của phiên bản hiện tại của Socket.io Khách hàng (1.4.8) có vẻ như tắt, removeAllListeners, removeEventListener đều trỏ đến các chức năng tương tự.

Gọi bất kỳ tên nào trong số đó, cung cấp tên sự kiện và/hoặc gọi lại, cho kết quả mong muốn. Không cung cấp bất cứ điều gì ở tất cả dường như để thiết lập lại tất cả mọi thứ.

Hãy thận trọng với đối số fn/callback. Nó phải là cùng một ví dụ được sử dụng trong mã.

Ví dụ:

var eventCallback = function(data) { 
    // do something nice 
}; 
socket.off('eventName', eventCallback); 

sẽ làm việc như mong đợi.

Ví dụ (cũng sẽ làm việc):

function eventCallback(data) { 
    // do something nice 
} 
socket.off('eventName', eventCallback); 

Hãy thận trọng rằng callback bạn đang cố gắng để loại bỏ là một trong đó bạn được thông qua năm (một này có thể mang lại rất nhiều sự nhầm lẫn và thất vọng). Ví dụ này thực hiện một wrapper xung quanh gọi lại ban đầu, cố gắng loại bỏ mà sẽ không làm việc như gọi lại thực được thêm vào được một trường hợp đóng cửa không được tiết lộ: http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/

Dưới đây là liên kết với dòng cụ thể trong codebase: https://github.com/socketio/socket.io-client/blob/master/socket.io.js#L1597

+1

Câu trả lời này cần nhiều phiếu bầu hơn, vì hầu hết các câu trả lời khác không đầy đủ và/hoặc hết hạn. –

1

Vì tôi đã có một điểm khó khăn khiến công việc này cho rằng tôi sẽ kêu vang ở đây, cùng với một câu trả lời được cập nhật tốt đẹp cho năm 2017. Nhờ @Pjotr ​​đã chỉ ra rằng nó phải là cùng một cá thể gọi lại.

Ví dụ với Angular2 TypeScript trong dịch vụ socket-io.subscriber. Lưu ý trình bao bọc "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); 
    } 
Các vấn đề liên quan