2

我使用 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但我没有运气。

4

1 回答 1

2

我终于设法弄清楚了。我查看了 JS 文件并设法将其归结为这样一个事实,即如果 Laravel channels.php 检查谁可以收听频道没有返回用户模型实例,则此行中的代码部分实际上不会引发错误try catch正如它应该。

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

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

如果$user没有通过if检查 Laravel 将返回false。由于它没有返回 JSON 并且只是错误的,我认为它应该记录响应主体没有通过该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 是否没有返回用户模型实例。

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

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

无论如何,要真正返回用户,请确保您使用 Laravel 的身份验证系统登录。如果你不使用它,你可能需要做一些工作才能让它工作。如果你不使用它,那么Laravel 中的这个函数会抛出 403 错误,因为它找不到你登录

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

然后在您的 channels.php 文件中,确保您正在执行的检查实际上是在从 auth 检查 Broadcaster.php 文件的回调函数中返回 $user 。像这样的东西:

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

这是一个超级简单的私人/在线频道,但有一个登录用户并返回 $user 这不会抛出这个错误。

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

window.Echo = new Echo({
    broadcaster:  'socket.io',
    host: window.location.origin + ':6001'
});
于 2017-08-20T13:36:28.270 回答