Как отказаться от подписки на socket.io? - программирование
Подтвердить что ты не робот

Как отказаться от подписки на 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;
4b9b3361

Ответ 1

От взгляда на источник socket.io.js(не удалось найти его в документации в любом месте), я нашел эти две функции:

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

Я успешно использовал removeAllListeners в своем приложении; вы должны быть в состоянии выбрать из них:

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

Кроме того, я не думаю, что ваше решение cbProxy = _blank действительно работает; это повлияет только на переменную cbProxy, а не на фактическое событие socket.io.

Ответ 2

Если вы хотите создать слушателей, которые "прослушивают" только один раз, используйте socket.once('news',func). Socket.io автоматически отключит слушателя после случившегося события - он называется "volatile listenener".

Ответ 3

Глядя на код текущей версии Socket.io Client (1.4.8), кажется, что off, removeAllListeners, removeEventListener все указывающие на одну и ту же функцию.

Вызов любого из них, предоставление имени события и/или обратного вызова, дает желаемый результат. Не предоставление чего-либо вообще похоже на reset все.

Пожалуйста, будьте осторожны с аргументом 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

Ответ 4

Socket.io версия 0.9.16 реализует removeListener, но не off.

Вы можете использовать removeListener вместо off при отмене подписки или просто реализовать off следующим образом:

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

Если вы используете подход подписки на подписку

Ответ 5

Я обнаружил, что в 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;
    };

Ответ 6

Удаление прослушивателя событий на клиенте

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

Ответ 7

Чтобы добавить к @Andrew Magee, вот пример отказа от подписки на события socket.io в Angular JS и, конечно же, работает с 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);
});

Ответ 8

Также на клиенте 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);

Ответ 9

Так как у меня было место неприятностей, и эта работа показала, что я тоже звоню вместе с хорошим обновленным ответом на 2017. Благодаря @Pjotr ​​за то, что он должен быть одним и тем же экземпляром обратного вызова.

/p >

Пример с Angular2 TypeScript в службе socket-io.subscriber. Обратите внимание на оболочку 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);
  }