Nice programing

socket.io 구독에서 구독을 취소하는 방법은 무엇입니까?

nicepro 2020. 12. 28. 22:34
반응형

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.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이벤트 구독 방식을 사용하는 경우 이벤트 구독을 off취소 할 때 위의 Backbone 호출을 구현해야 합니다.


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

이 작업을 수행하는 데 문제가 있었기 때문에 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);
  }

클라이언트에서 이벤트 리스너 제거

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

To add to @Andrew Magee, here is an example of unsubscribing socket.io events in Angular JS, and of course works with Vanilla JS:

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

Listen for events:

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);
});

Also on java client, it can be done the same way with the Javascript client. I've pasted from 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);

Pre-store the events using an array, and by the time you need to unsubscribe them, use the off method, which is a built in method from 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")

This has helped me in both Angular 8 and React 16.8:

receiveMessage() {
    let newCallback = (data) => {            
        this.eventEmitter.emit('add-message-response', data);
    };
    this.socket.on('add-message-response', newCallback);

    this.subscriptions.push({key: 'add-message-response', callback: newCallback});
}

receiveMessageRemoveSocketListener() {
    this.findAndRemoveSocketEventListener('add-message-response');
}

findAndRemoveSocketEventListener (eventKey) {
    let foundListener = this.subscriptions.find( (subscription) => subscription.key === eventKey );

    if(!foundListener) {
      return;
    } 

    this.socket.removeListener(foundListener.key, foundListener.callback);
    this.subscriptions = this.subscriptions.filter( (subscription) => subscription.key !== eventKey );
}

Reason for using an Array of Subscriptions is that when you Subscribe to an event multiple times and you don't remove an unsubscribed subscription from the Subscription list you will most probably be right at first time you remove the subscription from the list, but later subscriptions will not be removed as you will be finding first instance only every time you unsubscribe the event.

You can simply call receiveMessage(); to subscribe to an the event and receiveMessageRemoveSocketListener(); to Unsubscribe.

ReferenceURL : https://stackoverflow.com/questions/9418697/how-to-unsubscribe-from-a-socket-io-subscription

반응형