Angenommen, es gibt Objekte, die einen Socket-Server wie folgt abonnieren:
socket.on('news', obj.socketEvent)
Diese Objekte haben eine kurze Lebensdauer und werden häufig erstellt, wodurch viele Abonnements generiert werden. Dies scheint ein Speicherleck und eine fehleranfällige Situation zu sein, die auf diese Weise intuitiv verhindert würde:
socket.off('news', obj.socketEvent)
bevor das Objekt gelöscht wird, aber leider gibt es keine off Methode im Socket. Gibt es eine andere Methode, die dafür gedacht ist?
Bearbeiten: Nachdem ich keine Antwort gefunden habe, weise ich eine leere Methode zu, um die Wrapper-Methode für den ursprünglichen Ereignishandler zu überschreiben, ein Beispiel folgt.
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;
Als ich mir die Quelle von socket.io.js ansah (konnte es nirgendwo in der Dokumentation finden), fand ich diese beiden Funktionen:
Außerdem halte ich deine Lösung nicht für cbProxy = _blank würde tatsächlich funktionieren; das würde nur die betreffen cbProxy Variable, kein tatsächliches socket.io-Ereignis.
Das scheint zu funktionieren, das Ereignis verschwindet aus SocketNamespace, obwohl ich diesen Teil noch ausgiebig testen muss. Außerdem hatten Sie Recht mit der Proxy-Lösung, daher wurde sie aus Spaß aktualisiert
– Bijou-Trouvaille
14. März 2012 um 14:47 Uhr
Was funktioniert nicht? cbProxy war eine vom OP definierte Callback-Methode.
– Andrew Magee
11. August 2015 um 3:04 Uhr
Wenn Sie Listener erstellen möchten, die nur einmal “zuhört”, verwenden Sie socket.once('news',func). Socket.io wird den Listener automatisch zerstören, nachdem das Ereignis passiert ist – es heißt “volatile listener”.
Pjotr
Wenn man sich den Code der aktuellen Version von Socket.io Client (1.4.8) ansieht, scheint es so aus, AlleListener entfernen, EventListener entfernen zeigen alle auf die gleiche Funktion.
Das Aufrufen einer davon, Angabe des Ereignisnamens und/oder Rückrufs, führt zum gewünschten Ergebnis. Nichts zur Verfügung zu stellen scheint alles zurückzusetzen.
Bitte seien Sie vorsichtig mit der fn/Rückruf Streit. Es muss dieselbe Instanz sein, die im Code verwendet wird.
Beispiel:
var eventCallback = function(data) {
// do something nice
};
socket.off('eventName', eventCallback);
Würde wie erwartet funktionieren.
Beispiel (funktioniert auch):
function eventCallback(data) {
// do something nice
}
socket.off('eventName', eventCallback);
Bitte seien Sie vorsichtig, dass der Rückruf, den Sie zu entfernen versuchen, derjenige ist, den Sie weitergegeben haben (dieser kann viel Verwirrung und Frustration stiften). Dieses Beispiel implementiert einen Wrapper um den anfänglichen Callback, der zu versuchen, ihn zu entfernen, würde nicht funktionieren, da der wirklich hinzugefügte Callback eine nicht offengelegte Abschlussinstanz ist: http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/
Diese Antwort benötigt mehr Upvotes, da die meisten anderen unvollständig und/oder extrem veraltet sind.
– Anson Kao
28. Oktober 2016 um 21:37 Uhr
Wenn Sie verwenden socket.io-client npm-Paket, dann funktioniert dies am besten, da removeAllListeners() ist parameterlos (also können Sie nicht angeben eventName).
– Martin Schneider
2. April 2018 um 13:48 Uhr
Weder der Rückruf von Off feuert, noch funktioniert das Off, wenn ein Rückruf gegeben wird.
Socket.io Version 0.9.16 implementiert removeListener aber nicht off.
Sie können verwenden removeListener Anstatt von off bei der Abmeldung, oder einfach umsetzen off folgendermaßen:
var socket = io.connect(url);
socket.off = socket.removeListener;
Wenn Sie das Backbone verwenden listenTo Ereignisabonnement-Ansatz müssen Sie die oben genannten als Backbone-Aufrufe implementieren off beim Abbestellen von Veranstaltungen.
Ich habe festgestellt, dass in socket.io 0.9.11 und Chrome24 socket.io removeListener nicht funktioniert.
Diese modifizierte Version funktioniert bei mir:
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;
};
Josua Ohana
Da ich ein paar Probleme hatte, diese Arbeit zu machen, dachte ich, ich würde mich auch hier einklinken, zusammen mit einer netten aktualisierten Antwort für 2017. Danke an @Pjotr für den Hinweis, dass es dieselbe Callback-Instanz sein muss.
Beispiel mit Angular2 TypeScript in einem socket-io.subscriber Dienst. Beachten Sie den Wrapper „newCallback“.