user773737
user773737

Reputation:

socket.io Removing specific listener

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.

Upvotes: 83

Views: 86750

Answers (4)

turtlet
turtlet

Reputation: 43

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.

Upvotes: 0

Tod
Tod

Reputation: 2524

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.

Upvotes: 0

Israfel
Israfel

Reputation: 1692

//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

Upvotes: 141

Lyn Headley
Lyn Headley

Reputation: 11588

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

Upvotes: 54

Related Questions