Laravel Echo 不会捕获 socket.io 的事件

Laravel Echo won't catch events with socket.io

我将 Redis 与 Socket.io 一起使用来设置实时更新,但 Laravel Echo 没有捕获事件。

如果我使用 io() 的实例,它工作得很好。这是我在 vue 应用程序中监听事件的代码:

不会捕获事件

window.Echo.channel('users')
    .listen('UserCreated', event => {
            console.log(event);
            this.all_users.push(event.user);
            this.filter_data();
    });

将捕获事件

window.socket = io(window.location.origin+':3000');
window.socket.on('users:App\Events\UserCreated', function(data){
    console.log(data);
    console.log('from socket');
    this.all_users.push(data.user);
    this.filter_data();
}.bind(this));

我的节点js代码推送事件。

var server = require('http').Server();

var io = require('socket.io')(server);

var Redis = require('ioredis');

var redis = new Redis();

redis.subscribe('users', function(error, count){
    console.log(error);
    console.log(count);
});

redis.on('message', function(channel, message){
    console.log(channel);
    message = JSON.parse(message);
    console.log(message);
    const emmitChannel = `${channel}:${message.event}`;
    console.log(emmitChannel);
    io.emit(emmitChannel, message.data);
});

server.listen(3000);

我的Laravel活动广播

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;


//Models
use App\User;

class UserCreated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;

        $this->dontBroadcastToCurrentUser();
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return ['users'];
    }
}

我试过更改事件传递给 Laravel Echo 的方式,因为默认情况下它接收事件的方式是 users:App\Events\UserCreated,但我没有成功。

我终于弄明白了。我查看了 JS 文件并设法将其归结为 the code in this linetry catch 部分实际上不会抛出错误,如果 Laravel channels.php 检查谁可以听频道没有 return 用户模型实例。

Channels.php 中的类似内容会抛出该错误:

Broadcast::channel('users', function ($user) {
    if($user->type == 'admin'){
         return $user;
    }else{
         return false;
    }
});

如果 $user 没有通过 if 检查 Laravel 将 return false。因为它不是 returning JSON 并且只是 false 我认为它应该记录响应主体没有通过 JSON.parse() 函数所以你可以在终端中看到它。像这样:

try {
     body = JSON.parse(response.body);
} catch (e) {
     Log.warning('Response body provided is not expected JSON. Response body provided ${response.body}');
     body = response.body;
}

这样我们可以查看 Laravel 是否 return 用户模型实例。

因此,当您没有按预期获得用户模型实例时,没有用户对象供代码附加 sockedId,因为它未定义。从来没有任何 JSON 来制作对象。

我认为如果您没有获得用户实例而不是尝试附加套接字 ID,代码应该停止尝试连接到状态或专用频道。

无论如何,要真正 return 一个用户,请确保您已登录 using Laravel's Auth system. If you didn't use that you might have to do some work around to get it to work. If you are not using it then this function in Laravel will throw a 403 error because it can't find you to be logged in

我不得不将检查密码哈希算法的函数重写为提供程序的自定义算法,这样我就不会弄乱 Laravel 核心并使用户模型扩展 class Laravel正在寻找

然后在你的 channels.php 文件中确保你正在做的检查你实际上是 return 在来自 auth 的回调函数中检查 $user 检查 Broadcaster.php文件确实如此。像这样:

Broadcast::channel('users', function ($user) {
     return $user;
});

这是一个超级简单的 private/presence 频道,但是有一个登录用户和 returning $user 这不会抛出这个错误。

此外,请确保您在 Echo 实例中调用 socket.io,如下所示:

window.Echo = new Echo({
    broadcaster:  'socket.io',
    host: window.location.origin + ':6001'
});