Closed Neha3011 closed 4 years ago
I can confirm this issue as well. Our code does:
const channel = pusher.subscribe(`presence-${channelId}`);
channel.bind('client-eventName', (data) => {
// do the things
});
It would seem that channel
can get instantiated multiple times during the lifecycle of our app. It does not exist more than one in the pusher.channels
object, but it definitely exists multiple times in memory. And when the pusher events come in, the thing fires locally many times (depending on how many times that thing was instantiated).
Is there a better way to check if the subscription already exists?
Calling pusher.subscribe
a second time with the same channel name will return the same channel object as the first call. It only exists once in memory (see here). You can get a list of all subscribed channels using pusher.allChannels()
.
However I think your problem is that you are making multiple calls to bind
with the same callback. This will result in the same callback being called multiple times when the event occurs. You could make use of unbind
before you add new callbacks (see here), or change your application so you're not calling bind
multiple times.
Thanks @TomKemp. Just curious how do you know we are making multiple calls to bind
with the same callback? Is that just a common issue?
No problem @stueynet. I don't know that for sure, but that's what it sounds like from your description. You said:
channel can get instantiated multiple times during the lifecycle of our app
If channel
is getting instantiated multiple times then bind
is probably being called multiple times too because they are often called together. And calling bind
with the same callback multiple times would lead to your callback firing multiple times when the event is triggered.
We are finding that it’s not a matter of mutiple bindings but rather duplication of that channel object in memory somehow. So if it exists twice, then the events are handled twice. We tested by adding a random key to that object and over time we see that the pusher event is handled by different versions of channel. It’s super strange.
Was a solution for this ever found? I'm facing a similar issue in my Angular application where if I navigate away from my component, then back, a new identical event object is generated . I checked the pusher debug console and only one event is being registered so it seems this is happening in memory somehow.
This is very strange. @stueynet / @djcurtis2 are you able to reproduce this in a minimal example so I can try to see what's happening?
I actually figured out what was happening. Since I was binding to the channel on ngOnInit, when I navigated to another component, then back to the original it was adding another bind to the channel. Unbinding to the channel in my ngOnDestroy event solved the issue for me.
The problem is that, every time the application is started, a new Pusher client is instantiated. Hence I try to list the channels of the current Pusher client and there really is only one. But in reality there are other Pusher clients from previous instances of the application. As the picture shows. every time I open the app, a new client is started and the previous client reference is lost by the application.
I would like to know how to use the same Pusher client, or how to do so once a new Pusher with the same channel_id as the previous one has been created, a finished application can be terminated.
The problem is that, every time the application is started, a new Pusher client is instantiated. Hence I try to list the channels of the current Pusher client and there really is only one. But in reality there are other Pusher clients from previous instances of the application. As the picture shows. every time I open the app, a new client is started and the previous client reference is lost by the application.
I would like to know how to use the same Pusher client, or how to do so once a new Pusher with the same channel_id as the previous one has been created, a finished application can be terminated.
Were you able to solve the mystery?
I am encountering a similar issue. Currently if I minimise Chrome, and put the laptop to sleep for a few minutes then I get duplicate responses.
I have made sure that all of our code doesn't re-bind events and re-instantiate pusher, however I can see the Pusher state changing and reconnecting when I re-open Chrome after a few seconds.
At this point I would actually rather disable the auto-subscribe to the channels and just handle it myself but not sure how to go about this?
I ran into this issue and I solved it by making sure to use channel.unbind
when appropriate. It is possible to bind the same callback multiple times.
Pusher Java lib got the option to bind events along with channel subscription.
subscribe(final String channelName, final ChannelEventListener listener, final String... eventNames)
If pusher-js got a similar option, then it should avoid binding an event multiple times.
I think You have to unsubscribe the currently subscribed channel before subscribing to any other channel. I know it sounds weird!
There's been very little activity on this issue, and I'm not sure how to go about debugging with the information we have now so I'm going to close it.
If you're experiencing this issue and are able to provide more information to help debug it, please feel free to reopen
This helped me solve this issue on my system. (the Laravel Echo tab of the examples in the below link)
Using laravel-websockets and pusher-php-server on the backend and React, laravel-echo and pusher-js on the front end.
I was getting the above 2 callbacks being fired for one event after joining, leaving and joining the channel again.
My code was running Echo.leave(channelName)
to leave a channel but this wasn't unbinding the callbacks. So my code now loops through the callbacks and runs channel.stopListening(eventName)
to unbind each of them before leaving the channel
below are my redux thunks for dispatching
export const joinChannel = (channelName, eventHandlers = []) => (dispatch) => {
const channel = window.Echo.private(channelName)
eventHandlers.forEach(({ name, handle }) => {
channel.listen(name, handle)
})
dispatch(joinChannelSuccess(channelName))
}
export const leaveChannel = (channelName, eventHandlers = []) => (dispatch) => {
const channel = window.Echo.private(channelName)
eventHandlers.forEach(({ name }) => {
channel.stopListening(name)
})
window.Echo.leave(channelName)
dispatch(leaveChannelSuccess(channelName))
}
for anyone using this with react native you have to unbind after the callback heres an example
var channel = pusher.subscribe('test');
channel.bind('assigned', function(data) {
if(data.message){
console.log("some message")
}
}, channel.unbind());
for laravel echo
const echo = Echo.private(`gmail.token.expired.${user.id}`);
echo.listen('.gmail.token.expired', (event) => {
// some action
}, echo.stopListening('.gmail.token.expired'))
I was having this same issue, solved by adding unbind before I bind an event, example:
channel.unbind('event').bind('event', (result) => {
//my code here
});
I was having this same issue, solved by adding unbind before I bind an event, example:
channel.unbind('event').bind('event', (result) => { //my code here });
Sir...i use your script..but i got error (The listener argument must be type of function. Received undefined)..how to handle this error?
To solve this, you need to unbind the channel before binding.
pusherClient.subscribe(1234); pusherClient.bind(1234); pusherClient.bind("incoming-message", (text) => { console.log(text); });
See here for more info
I had to add a cleanup function on the useEffect
useEffect(() => {
const subscribeToNotificationsChannel = async () => {
try {
pusherInstance.unsubscribe(channelName);
const channel = pusherInstance.subscribe(channelName);
channel.bind(PUSHER_CHAT_EVENTS.CHAT_MESSAGE_RECEIVED, (data: any) => {
console.log('Received notification from chat:', data);
// queryClient.invalidateQueries({ queryKey: [queryKey] });
queryClient.setQueryData([queryKey], (prev) => {
console.log(prev, data);
return {
pages: [
[data, ...prev.pages[0]],
...prev.pages.slice(1), // Keep the rest of the pages unchanged
],
pageParams: prev.pageParams,
};
});
});
// Bind to subscription success event
channel.bind('pusher:subscription_succeeded', (data: any) => {
console.log('Subscription succeeded:', data);
});
channel.bind('pusher:subscription_error', (err: any) => {
console.log(err);
});
} catch (error) {
console.error('Error subscribing to notifications channel:', error);
}
};
subscribeToNotificationsChannel();
return () => {
pusherInstance.unsubscribe(channelName);
};
}, [pusherInstance, channelName, queryClient, queryKey]);
I am facing issue while using authenticated pusher events. When I get any event from pusher, in network tab I see only one event, but when I log inside my code, I get multiple log statements.
My code looks something like this this.privateChannel.bind('eventName', data => { console.log(data) });
My pusher version is 4.2.2. Thank you.