如何在前端获取 socket.on 函数?事件被触发和处理。我正在使用 socket.io、NodeJS 服务器和 Redis.io

Posted

技术标签:

【中文标题】如何在前端获取 socket.on 函数?事件被触发和处理。我正在使用 socket.io、NodeJS 服务器和 Redis.io【英文标题】:How to fetch socket.on function in frontend? The Event is triggered and processed. I'm using socket.io, NodeJS server, and Redis.io 【发布时间】:2021-12-03 15:13:14 【问题描述】:

*前端

正如您在代码中看到的那样。我正在尝试制作聊天应用程序。我发送的消息被触发,我的事件正在处理中。但问题是我无法从接收方接收消息。我是一名初级开发人员,并通过 youtube 教程制作应用程序。谢谢...

<script>
     $(function ()
            let $chatInput = $(".chat-input");

            let $chatInputToolbar = $(".chat-input-toolbar");

            let $chatBody = $(".chat-body");

            let $messageWrapper = $("#messageWrapper");


            let user_id = " auth()->user()->id ";

            let ip_address = 'http://127.0.0.1';

            let socket_port = '8005';

            let socket = io(ip_address + ':' + socket_port);

            let friendId = " $friendInfo->id ";
            
            socket.on('connect', function() 
                
                socket.emit('user_connected', user_id);
            );

            socket.on('updateUserStatus', (data) => 
                let $userStatusIcon = $('.user-status-icon ');
                $userStatusIcon.removeClass('text-success');
                $userStatusIcon.attr('title', 'Away');
                

                $.each(data, function (key, val) 
                    if (val !== null && val !== 0) 
                       
                        let $userIcon = $(".user-icon-"+key);
                        $userIcon.addClass('text-success');
                        $userIcon.attr('title','Online');
                    
                );

            );

            $chatInput.keypress(function (e) 
                let message = $(this).html();                       //text
                if (e.which === 13 && !e.shiftKey) 
                    $chatInput.html("");
                    sendMessage(message);
                    return false;

                
            );

              function sendMessage(message) 
                let url = " route('message.send-message') ";
                let form = $(this);
                let formData = new FormData();
                let token = " csrf_token() ";

                formData.append('message', message);
                formData.append('_token', token);
                formData.append('receiver_id', friendId);

                appendMessageToSender(message);

                $.ajax(
                    url: url,
                    type: 'POST',
                    data: formData,
                        processData: false,
                        contentType: false,
                        dataType: 'JSON',
                    success: function (response) 
                        if (response.success) 
                            console.log(response.data);
                        
                    
                );


            

              function appendMessageToSender(message) 
                let name = ' $myInfo->name ';
                let image = '!! makeImageFromName($myInfo->name) !!';

                let userInfo = '<div class="col-md-12 user-info">\n' +

                                    '<div class="chat-image">\n' + image +
                                       
                                    '</div>\n' +

                                    '\n' +

                                    '<div class="chat-name font-weight-bold">\n' +

                                        name +

                                        '<span class="small time text-gray-500" 
                                        title="'+getCurrentDateTime()+'">\n' +

                                        getCurrentTime()+'</span>\n' +

                               
                                    '</div>\n' +

                                    '</div>\n';

                
                                    
                 let messageContent = '<div class="col-md-12 message-content">\n' +

                                            '<div class="message-text">\n' +
                                                message +
                                            '</div>\n' +

                                            '</div>';     
                                            
                                            

                let newMessage = '<div class="row message align-item-center mb-2">'
                +userInfo + messageContent +
                '</div>';

                $messageWrapper.append(newMessage);

            

           

            function appendMessageToReceiver(message) 
            let name = ' $friendInfo->name ';
            let image = '!! makeImageFromName($friendInfo->name) !!';
           
            let userInfo = '<div class="col-md-12 user-info">\n' +
                '<div class="chat-image">\n' + image +
                '</div>\n' +
                '\n' +
                '<div class="chat-name font-weight-bold">\n' +
                name +
                '<span class="small time text-gray-500" 
                title="'+dateFormat(message.created_at)+'">\n' +
                timeFormat(message.created_at)+'</span>\n' +
                '</div>\n' +
                '</div>\n';
            let messageContent = '<div class="col-md-12 message-content">\n' +
                '<div class="message-text">\n' + message.content +
                '</div>\n' +
                '</div>';
            let newMessage = '<div class="row message align-items-center mb-2">'
                +userInfo + messageContent +
                '</div>';
                $messageWrapper.append(newMessage);
           
            
            



            
                
                appendMessageToReceiver(message);
                
                
            );

我想我在 socket.on 函数中遗漏了一些东西: socket.on("private-channel:App\Events\PrivateMessageEvent", 函数(消息)

            socket.on("private-channel:App\\Events\\PrivateMessageEvent", function (message)
            
                
                appendMessageToReceiver(message);
                
                
            );


        );

后端服务器

var app = require('express')();


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

var io = require('socket.io')(http, 
    cors: 
        origin: "*",
        
      
);

var Redis = require('ioredis');
var redis = new Redis();

var users = [];

http.listen(8005, function() 
    console.log('Listening to port 8005');

);

redis.subscribe('private-channel', function() 
    console.log('subscribed to private channel');
);

redis.on('message', function(channel, message) 
    message = JSON.parse(message);
    console.log(message);
    if (channel == 'private-channel') 
        let data = message.data.data;
        let receiver_id = data.receiver_id;
        let event = message.event;

        io.to('$users[receiver_id]').emit(channel + ':' + event, data);

    
    
);

io.on('connection', function (socket) 
    socket.on("user_connected", function (user_id) 
            users[user_id] = socket.id;
            io.emit('updateUserStatus', users);
            console.log("user connected "+ user_id);
    );

    socket.on('disconnect', function() 
        var i = users.indexOf(socket.id);
        users.splice(i, 1, 0);
        io.emit('updateUserStatus', users);
        console.log('users');
    );

);

PrivateMessageEvent

namespace App\Events;

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

class PrivateMessageEvent implements ShouldBroadcast

    use Dispatchable, InteractsWithSockets, SerializesModels;
    Public $data;

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

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    
        return new Channel('private-channel');

    

.env

这是我的 .env 文件。

APP_NAME=chat_application
APP_ENV=local
//App_key
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=chat_application
DB_USERNAME=root
DB_PASSWORD=


BROADCAST_DRIVER=redis
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="$APP_NAME"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="$PUSHER_APP_KEY"
MIX_PUSHER_APP_CLUSTER="$PUSHER_APP_CLUSTER

"

【问题讨论】:

【参考方案1】:

我注意到在您的服务器端代码中发出的事件存在一个问题,这里是发出套接字事件的代码

io.to('$users[receiver_id]').emit(channel + ':' + event, data);

因此,您尝试使用字符串插值和上述语法是不正确的。基本上,这只是一个字符串'$users[receiver_id]'。这个需要改成`$users[receiver_id]`,下面是更新后的代码

io.to(`$users[receiver_id]`).emit(channel + ':' + event, data);

因此,当使用字符串插值时,您需要使用反引号而不是单引号。 还有一点要确保,io.to('$users[receiver_id]').emit(channel + ':' + event, data); 中的 channel + ':' + event 与客户端代码中的客户端事件相同 - "private-channel:App\\Events\\PrivateMessageEvent"

socket.on("private-channel:App\\Events\\PrivateMessageEvent", function (message)                 
  appendMessageToReceiver(message);
);

【讨论】:

以上是关于如何在前端获取 socket.on 函数?事件被触发和处理。我正在使用 socket.io、NodeJS 服务器和 Redis.io的主要内容,如果未能解决你的问题,请参考以下文章

Socket.io 事件多次发出

Socket.on() 监听任何事件

如何检测未注册的socket.io事件?

android 监听屏幕是不是被触碰过?

在 React 中,如何将“this.state”作为参数传递给“socket.on”回调函数?

socket.on 事件在每次响应时都会重复多次