Question title may be little confusing, I tried my best to explain it.
I've got laravel-echo-server
, redis
(for queueing), and Laravel echo
set up. All I want is to send a message via an input, and update the messages feed for everyone on the page; essentially a chat room.
Everything works, except for the fact it's slow as hell, but I'm new to Laravel Echo
and Vue
.
if I sent one message, it's fine, but then when I send another message I get two responses. Send a third message three responses and so on...
What exactly am I doing wrong? I have checked socket.io
/laravel-echo-server
is only connecting to the channel once, and my broadcast
is only being sent once (checking queue worker it's only processing the request), so how is it being repeated exponentially?
This is my app.js:
const chatWindow = new Vue({
el: '#chatWindow',
data: {
messages: []
},
methods: {
sendMessage: function () {
this.$http.post('/chat', {message: this.message}).then((response) => {
window.Echo.channel('test-chat-channel')
.listen('MessageSent', (event) => {
console.log(event.message);
// this.messages.push(event.message);
});
}, (response) => {
// error callback
});
this.message = '';
}
},
props: ['message']
});
This is my chat view:
<div id="chatWindow" class="col-sm-7">
<h1 class="text-center no-top">Chat</h1>
<div class="chat-window">
<ul>
<li v-for="message in messages">@{{ message }}</li>
</ul>
<div class="form-group">
<input title="Send Message" v-model="message" @keyup.enter="sendMessage" class="form-control" placeholder="Send message...">
</div>
</div>
</div>
Just in case they're relevant here is my route:
Route::post('/chat', function (Request $request) {
event(new MessageSent($request->message));
});
and my event:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class MessageSent implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public $message;
public function __construct($message)
{
$this->message = $message;
}
public function broadcastOn()
{
return new Channel('test-chat-channel');
}
}
I am using Redis PubSub in the application I am currently building and have had to fight the same problem. While I don't know laravel-echo-server enough to advise you specifically on how to fix it, I can describe the likely reason for this symptom.
Your configuration is subscribing to the Redis channel on each cycle, and that subscription is not transient. Each time you subscribe, you create a new listener. Each time you publish, Redis sends the message to all listeners/subscribers. If a single client has subscribed three times, it will receive that message three times. You need to either recognize that you are subscribed and not duplicate it, or you need to unsubscribe after each cycle.
One thing to note is that the Redis instance should either publish or subscribe, but not both. laravel-echo-server is probably handling that for you.
Redis normally returns the number of subscribers receiving a message on each publish. This helped me diagnose the problem, especially since I am running private channels and should have 1, and only 1, listener for each message. Redis also has a "numsub" command that returns the number of listeners on a channel.
I noticed that your sendMessage function uses the listen method. It's a shot in the dark, but is that where you get multiple subscriptions?
Either way, I'd be glad to help further if you have a specific question that I can answer.
For anyone coming across this who is seeing a similar issue where:
It could be that your Pusher connection is not being destroyed when each page is loaded. This can happen if you have a global component which has been registered on multiple pages. To overcome this issue, you could register your listener component within a master layout component, preventing multiple listeners from being cached.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With