Laravel Echo 重复监听事件 n 次广播已被制作

Posted

技术标签:

【中文标题】Laravel Echo 重复监听事件 n 次广播已被制作【英文标题】:Laravel Echo repeating listen event for n times broadcast has been made 【发布时间】:2017-04-12 19:29:27 【问题描述】:

问题标题可能有点混乱,我已尽力解释。

我已经设置了laravel-echo-serverredis(用于排队)和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']
);

这是我的聊天视图

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

以防万一他们在这里是我的路线

Route::post('/chat', function (Request $request) 
    event(new MessageSent($request->message));
);

还有我的活动

<?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');
    

【问题讨论】:

【参考方案1】:

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

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

需要注意的一点是,Redis 实例应该发布或订阅,但不能同时发布。 laravel-echo-server 可能正在为您处理。

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

我注意到您的 sendMessage 函数使用了监听方法。这是在黑暗中拍摄的,但这是您获得多个订阅的地方吗?

无论哪种方式,如果您有我可以回答的具体问题,我很乐意提供进一步帮助。

【讨论】:

我想你可能在这里有所收获。我认为我应该做的是分离监听方法,而不是在成功请求的响应回调中使用它......这可能是导致问题的原因 - 我实际上不需要响应回调,只是一个错误回调,并且侦听请求之外的事件以避免过度订阅。谢谢你,我会试一试,让你知道! @A.Appleby 这对我来说也很有可能。 @A.Appleby 怎么样?你解决了吗?我可以帮忙吗? 很抱歉,我以为我已经评论并标记了这个......是的,我根据您的回答提供的信息解决了这个问题。尽管您没有提供确切的答案,但由于您的理论是准确的,因此我很快就解决了这个问题。因此,我已将您的答案标记为正确。我基本上是在创建 n 个监听事件,因此每个创建的监听事件都附加到消息 - 这就是为什么它只会附加到每个用户输入的消息 n 次;不是整体,因为它们在不同的实例上运行。非常感谢! 我明白了。这也发生在我身上。所以这可能是因为当同一个用户打开同一页面的多个窗口时,他订阅了多次?【参考方案2】:

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

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

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

【讨论】:

以上是关于Laravel Echo 重复监听事件 n 次广播已被制作的主要内容,如果未能解决你的问题,请参考以下文章

Laravel echo 未收到事件

Laravel 事件广播没有被拾取 laravel-echo-server

laravel5.5事件广播系统实例laravel-echo + redis + socket.io

Laravel Echo + VueJS 广播/认证问题

Laravel 5.4 事件广播不适用于 vuejs

关于uniapp的事件监听,使用uni.$once和uni.$on导致的重复监听