Laravel Echo重复播放n次广播的事件

A. *_*eby 5 redis socket.io laravel vue.js

问题标题可能有点混乱,我尽力解释它.

我有laravel-echo-server,redis(排队),并Laravel echo设置.我想要的只是通过输入发送消息,并为页面上的每个人更新消息提要; 本质上是一个聊天室.

一切都有效,除了地狱的速度很慢,但我是新手Laravel EchoVue.

如果我发送了一条消息,那很好,但是当我发送另一条消息时,我会收到两条消息.发送第三条消息三个响应等等......

我究竟做错了什么?我已经检查socket.io/ laravel-echo-server只连接到通道一次,而我broadcast只被发送一次(检查队列工作者它只处理请求),那么它是如何以指数方式重复的?

这是我的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']
});
Run Code Online (Sandbox Code Playgroud)

这是我的聊天视图:

<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>
Run Code Online (Sandbox Code Playgroud)

以防它们在这里是相关的是我的路线:

Route::post('/chat', function (Request $request) {
    event(new MessageSent($request->message));
});
Run Code Online (Sandbox Code Playgroud)

和我的事件:

<?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');
    }
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*ero 5

对于遇到此问题且遇到类似问题的任何人:

  • 您有一个单页应用程序
  • 您已经定义了一个 Echo 监听器
  • 您已启用 Pusher 控制台日志并且仅看到收到的一个事件
  • 您只看到 Pusher 调试控制台中触发了一个事件
  • 您在调试控制台中看到正常操作(对正确通道的一次订阅、断开连接等)
  • 但是每次触发一个事件时,您的侦听器都会接收多个事件

加载每个页面时,您的 Pusher 连接可能不会被破坏。如果您有一个已在多个页面上注册的全局组件,则可能会发生这种情况。要解决此问题,您可以在主布局组件中注册侦听器组件,以防止缓存多个侦听器。


Ric*_*d_G 3

我在当前正在构建的应用程序中使用 Redis PubSub,并且不得不解决同样的问题。虽然我对 laravel-echo-server 的了解不够,无法具体建议您如何修复它,但我可以描述出现此症状的可能原因。

您的配置是在每个周期订阅 Redis 通道,并且该订阅不是暂时的。每次订阅时,您都会创建一个新的侦听器。每次发布时,Redis 都会将消息发送给所有侦听器/订阅者。如果单个客户端订阅了 3 次,它将收到该消息 3 次。您需要认识到您已订阅并且不重复订阅,或者您需要在每个周期后取消订阅。

需要注意的一件事是,Redis 实例应该发布或订阅,但不能两者兼而有之。laravel-echo-server 可能正在为您处理这个问题。

Redis 通常会返回每次发布时接收消息的订阅者数量。这帮助我诊断问题,特别是因为我正在运行私人频道,并且每条消息应该有 1 个且只有 1 个侦听器。Redis 还有一个“numsub”命令,用于返回通道上的侦听器数量。

我注意到你的sendMessage函数使用listen方法。这是一个盲目的尝试,但这就是你获得多个订阅的地方吗?

不管怎样,如果您有我可以回答的具体问题,我很乐意为您提供进一步的帮助。