Laravel echo listening is not receiving data

Published 3 months ago by andfelzapata

Hey everyone !

I'm building a real time notification feature for an app I'm working on. I' using Laravel 5.3, Node, Laravel Echo, Redis, and socket.io.

I have my events setup, node server listening on port 8888, redis pubsub is connection with node working. Everything on the backend is working.

One of my events:

class BecaCargada implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;

    public $usuario;

    public $mensaje;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(Usuario $usuario, $mensaje)
    {
        $this->usuario = $usuario;
        $this->mensaje = $mensaje;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('channel-notificaciones');
    }
}

When I generate this event it gets fired and publishes on the change successfully, I can see that on redis-cli and also on the nodeJS code thats subscribed and listening to the same channel.

The is the nodeJS code that listens on the same channel:

require ('dotenv').config();

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

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

const Redis = require('ioredis');

const redis = new Redis();

redis.subscribe('channel-notificaciones');

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

server.listen({
    host: process.env.NOTIFICACIONES_SOCKET_HOST,
    port: process.env.NOTIFICACIONES_SOCKET_PORT
});

And for my js code I only have this right now:

import Echo from "laravel-echo";

window._ = require('lodash');

window.io = require("socket.io-client");

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */
const echo = window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: `${process.env.APP_URL}:${process.env.NOTIFICACIONES_SOCKET_PORT}`
});


echo.channel('channel-notificaciones')
    .listen('BecaCargada', (e) => {
        console.log(e);
});

After running gulp and refreshing, I open another tab and trigger the event. If I open dev tools and look at the frames tab in the socket connection I can see the incoming events clearly, channel:EventName, payload.

But nothing shows on the console from the console.log(e) code. I've inspected the echo variable and everything seems ok, the namespace, the channel.

Any thoughts on what could be wrong ?

Thanks and happy coding =)

Best Answer (As Selected By andfelzapata)
khaledSMQ

@andfelzapata , @andfelzapata here is my full code and it's working i have tested

// /etc/supervisor/conf.d/laravel-worker.conf

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/vagrant/Code/Laravel/artisan queue:work redis --tries=3
autostart=true
autorestart=true
user=root
numprocs=8
redirect_stderr=true
stdout_logfile=/home/vagrant/Code/Laravel/storage/logs/worker.log

// from https://laravel.com/docs/5.3/queues#supervisor-configuration


// .env

APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://homestead.app
SOCKET_PORT=6001

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=redis

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_KEY=
PUSHER_SECRET=


// server.js
require('dotenv').config();

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

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

const Redis = require('ioredis');

const redis = new Redis();

redis.subscribe('all-channel');

console.log(process.env.SOCKET_PORT);

redis.on('message', function (channel, message) {
    const event = JSON.parse(message);
    io.emit(event.event, channel, event.data);
});

server.listen({
    port: process.env.SOCKET_PORT
});



// bootstrap.js
import Echo from "laravel-echo"

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: 'http://homestead.app:6001'
});


// home.blade.php
 
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="{{ elixir('js/app.js') }}"></script>

<script>

    document.onreadystatechange = () => {
        if (document.readyState === 'complete') {
            console.log("doc is ready");
            Echo.channel('all-channel').listen('ServerCreated', function(e) {
                console.log(e);
            });
        }
    };

</script>



/// route/web.php


Route::get('publish', function () {
    $data = [
        'type'    => 'erhelloror',
        'title'   => 'new article has been published',
        'message' => 'check it out',
        'url'     => 'url',
    ];
    event(new \App\Events\ServerCreated($data));
    return 'done';
});



/// App\Events\ServerCreated
// event

class ServerCreated implements ShouldBroadcast
{

    use InteractsWithSockets, SerializesModels;

    public $data;


    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(array $data = [])
    {
        $this->data = $data;
    }


    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('all-channel');
    }

}


don't forget to run

npm run dev
khaledSMQ

yesterday i face the same problem and i could figure out where is the problem, i end up to call listen method after all the dom is loaded.

also make sure in your blade file to load socket.io before app.js

andfelzapata

Thanks @khaledSMQ, I'm going to try that out later today.

khaledSMQ

Your welcome , sorry for late update. i think the problem is you have to listen for the jobs by running

php artisan queue:listen

andfelzapata

The events from the server are getting to the browser with no problem. I think the problem is with:

echo.channel('channel-notificaciones')
    .listen('BecaCargada', (e) => {
        console.log(e);
});

That piece of code is not doing anything, however, messages from the server to the browser are working, the browser is receiving data.

If I open dev tools and inspect the socket's frames, is see the incoming data.

khaledSMQ

What about

echo.channel('channel-notificaciones')
    .listen('BecaCargada', function(e) {
        console.log(e);
});

khaledSMQ

also in the frame you can see the entire event namespace or just a number ?

andfelzapata

Hi @khaledSMQ, i get the whole channel with event, namespace included.

khaledSMQ

Hi @andfelzapata i think the missing part in your node server

// need to add 'channel' like bellow 
io.emit(emmitChannel, channel, notificacion.data);


// update

    const notificacion = JSON.parse(message);
    const emmitChannel = notificacion.event;
    io.emit(emmitChannel, channel, notificacion.data);

geraldarcega

I also have the same problem with @andfelzapata, I've tried to follow all the solutions that @khaledSMQ suggests but still no luck. Any other solution? Thanks!

khaledSMQ

@geraldarcega can you provide more information

andfelzapata

I think a good idea would be to read Echo's source code. I'm planning on doing that soon. I'll update anything I find.

geraldarcega

I agree @andfelzapata, will do the same and also post an update if I got something.

@khaledSMQ I have exactly the same issue as the op. I'm just asking if there are any other options or set up that we have forgotten (based on the code that op posted) to include on either node server or in Echo.

andfelzapata

@geraldarcega from the docs you can read there is a Socket.io Server, haven't tried it though. I went and used a node server setup I had used in the past without Echo and in previous versions of Laravel.

Edit: from the docs https://github.com/tlaverdure/laravel-echo-server

andfelzapata

Testing plain io code works:

var socket = io(`${process.env.APP_URL}:${process.env.NOTIFICACIONES_SOCKET_PORT}`);

socket.on(`channel-notificaciones:App\\Events\\Notificaciones\\BecaCargada`, function (data) {
    console.log(data);
});
geraldarcega

I think I got something, this is only my initial findings, take a look at the generated Echo js, in my case line 271 to 284; { key: 'on', value: function on(event, callback) { var _this2 = this; var listener = function listener(channel, data) { if (_this2.name == channel) { callback(data); } }; this.socket.on(event, listener); this.bind(event, listener); } } Try to check the value of the listener parameter (channel, data), based on the condition in the IF statement, the channel must be a string, but what I get is Object, and the data is undefined, which is I think that the channel is not being past in the listener but only the data is being past, that's why the callback never fires.

Sign In or create a forum account to participate in this discussion.