How to unbind custom channel events?

At the moment, I’m using angularjs with phoenix and I want to know how can I unbind custom channel events.

In Angularjs, one way would be like this.

var unbindHandler = $scope.$on("channel_event", channelFunction); // returns a deregistration function

.... later down the line
unbindHandler() // event is unbinded
unbindHandler = null

When I try to do the same thing with with the channel object.

    var unbindHandler = channel.on("new_message", message => {
       ... code
   })

and call it

    unbindHandler()

I get an error saying that unbindHandler is not a function because it is undefined. Because of this I have to assume that channel.on doesn’t return a deregistration function for me to use so I can unbind when I’m done. What can I do?

I’ve tried to leave the channel(channel.leave()) hoping that it would automatically unbind but it still doesn’t.

It returns a ref:

var ref = channel.on("new_message", message => { ... });

channel.off("new_message", ref);

You could create a wrapper function:

function channelFunctionFactory(channel) {
   return function(event, callback) {
     var ref = channel.on(event, callback);
     return function() {
       channel.off(event, ref);
     }
   }
}

var channelFunction = channelFunctionFactory(channel);
var unbindHandler = channelFunction("new_message", message => { ... });
unbindHandler();

OK, so this is untested. I don’t know if it will work, but it gives you what you want (I think).

Thanks for the reply, but at least with angularjs, I don’t think it returns a ref.

To verify I did this

var channel = socket.channel("lobby", {});
console.log(channel.on("new_message", () => {
     console.log("Hello");
 }));  // This prints out undefined
console.log(channel) // Yet it still says that it binded "new_message". 

So is there any other way to get a handler or ref to the event?

Ah! I know what’s wrong.

It looks like the ref logic is only available in master right now.

You can do this:

function channelFunctionFactory(channel) {
   return function(event, callback) {
     channel.on(event, callback);
     return function() {
       channel.off(event);
     }
   }
}

var channelFunction = channelFunctionFactory(channel);
var unbindHandler = channelFunction("new_message", message => { ... });
unbindHandler();

Unfortunately it means you can’t bind to the same event multiple times. You could also try getting the updated phoenix.js from master.

1 Like

Thanks, that worked. I figured I was only able to bind to only one event at a time considering that when I joined a different channel, the number of bindings for each channel object was off. Much appreciated.

Though I have a question before I put this topic to rest.

If I do this

var channel = socket.channel("lobby", {});

Down the line I bind some events to that channel object and then I do this without unbinding the events

var channel = socket.channel("room", {});

Would it cause a memory leak for not calling channel.off on the previous channel object and initializing it with a new one? My intuition says yes but I’m not sure.

If not, then is there any point in unbinding in my case?