socket.io Removing specific listener
Asked Answered
A

4

82

I'm using Socket.io v0.9.16 and Chrome 34

I'm trying to remove a specific listener, or unsubscribe from a specific subscription

Something like this:

socket.on('testComplete',function(data){
    console.log('test complete',data);
}); 

function emitTest(){
    console.log('emitting test');
    socket.emit('test','first emit');
}

function removeListener(){
    socket.removeListener('testComplete');
}

If I call the emitTest function, and then the removeListener function, I still see the 'test complete' message when I call emitTest again. The listener should have been removed, if the socket function even works.

I'm looking for a way to remove a specific listener that actually works.

This answer says that removeListener doesn't work.

Is there any downside to just doing this:

socket.removeListener=function(name){
        if(socket.$events.hasOwnProperty(name)){
            delete socket.$events[name];
        }
    };

I marked an answer as correct, but I'm using the above in my code since it works better with my design.

Agretha answered 15/4, 2014 at 19:24 Comment(0)
I
141
//To unsubscribe all listeners of an event
socket.off('event-name');

//to unsubscribe a certain listener
socket.off('event-name', listener);

Note that socket.off, socket.removeListener, socket.removeAllListeners, socket.removeEventListener are synonyms.

This is tested on socket.io v1.4.3

Indisputable answered 11/1, 2016 at 7:47 Comment(4)
I'm using socket.io 2.0.x and can confirm this works both for specific listeners and without specifying a specific listener to just unbind all functions (including anonymous functions).Motorcade
With socket.io 2.3.0, the socket.off() event throws an error, if I invoke it without a second parameter, which has to be a function. I presume, the specific function that I want to remove.Overdo
I've managed to remove all the event listeners using socket.removeAllListeners("news"); found in this answer: https://mcmap.net/q/244421/-how-to-unsubscribe-from-a-socket-io-subscriptionOverdo
I'm using socket.io version 2.3.0 and off is not defined on the server side when obtaining the socket object through io.on(eventName, (socket) => {...}). However, removeListener works just fine in this case.Agama
R
54

You need to pass in the listener function to removeListener.

function testFun(data){
    console.log('test complete',data);
}

socket.on('testComplete', testFun); 

function emitTest(){
    console.log('emitting test');
    socket.emit('test','first emit');
}

function removeListener(){
    socket.removeListener('testComplete', testFun);
}
Ring answered 15/4, 2014 at 19:29 Comment(1)
Why twice as many? You just have to have a reference to the function you passed in. This is the way all EventEmitters on Node work, as well as the convention in browser libraries. If you have an unknown number of handlers registered for a given event and need to remove them all, I think your solution is sensible though.Henrie
V
0

Update 2023: All of the major browsers have decided against supporting getEventListeners. Only Chrome supports it from the command line!

If you're not using a function call, or even if you are the following worked for me:

getEventListeners(socket)['testComplete'][0].remove()

You could even loop through all the listeners attached and remove them.

for(var prop in getEventListeners(websocket))
{
    $(getEventListeners(websocket)[prop]).each(function() { this.remove()})
}

It's worth pointing out that although this works, it only works in Chrome at the moment.

Verada answered 6/3, 2017 at 14:54 Comment(0)
L
0

Old question, but answers here helped me. Below is a stripped version of my implementation.

Angular: 15.2.0 
socket.io-client: 4.6.1 
Chrome: Version 118.0.5993.118 (Official Build) (64-bit)

What I did was create a Map in my websocket service. I use it to store the callback function, with the event name as key.

eventHandlerMapper: Map<string, (response: any) => void> = new Map();

My listen() function looks like so: (Returning an Observable so my subscriber can handle the payload)

listen(eventName: string): Observable<any> {
    return new Observable((subscriber) => {
        const handler = (data: any) => subscriber.next(data);

        // register handler to socket for this event name
        this.socket.on(eventName, handler);

        // store for unlistening
        this.eventHandlerMapper.set(eventName, handler);
    });
}

To unlisten, I simply do this:

unlisten(eventName: string): void {
    this.socket.off(eventName, this.eventHandlerMapper.get(eventName));
}

By passing the ORIGINAL handler back into this.socket.off(), it unregisters the handler from the socket for the specified event name.

Referencing Socket.io Client API document:

https://socket.io/docs/v4/client-api/#socketoffeventname

I then checked the efficacy of my implementation by logging out my socket object and checking its list of registered callback functions, before and after listening/unlistening.

Lowercase answered 31/10, 2023 at 10:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.