很长一段时间以来,我一直在试图解决这个问题,但是我什么也没发现, 我正在尝试使用构建一个简单的私人聊天应用程序
我建立了聊天室,但有一个尚无法修复的错误, 问题是当我第一次打开聊天或在发送第一条消息时重新加载页面时,它会在正确的时间显示给接收者,但不会显示给所有者,尽管这是同时发送给两个用户的,但其他所有消息都会显示在正确的时间由两个用户决定,这是代码, 而且errorevent的功能相同,应该将错误消息发送给它的所有者,但不会通过socketio发送第一条消息。
server.js
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
var rediserror = new Redis();
redis.psubscribe('private-message-channel.*' , function(err , count) {
console.log('error is '+err+' and count is '+count);
});
redis.on('pmessage' , function(pattern ,channel , message) {
console.log('channel is '+channel+' and message is '+message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
rediserror.psubscribe('private-error-channel.*' , function(err , count) {
console.log('error is '+err+' and count is '+count);
});
rediserror.on('pmessage' , function( pattern ,channel , message) {
console.log("channel is " + channel + " and message is: " + message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
var redischatchannel = new Redis();
redischatchannel.psubscribe('private-chat-channel.*' , function(err , count){
console.log('error is '+err+' and count is '+count);
});
redischatchannel.on('pmessage' , function(pattern , channel , message) {
console.log("channel is "+channel +" and message is: "+message);
message = JSON.parse(message);
io.emit(channel+':'+message.event , message.data);
});
http.listen(3000, function () {
console.log('server lisening at port 3000');
});
chatroom.blade.php
@extends('layouts.app')
@section('content')
@if(!$messages)
<h3>No Messages in your chat with {{$to->name}} yet</h3>
@else
<div id="msgs">
@foreach($messages as $message)
<p><em><b>{{$message->fromusername}}</b></em> : {{$message->body}}</p>
<hr>
@endforeach
</div>
@endif
<form id="chatform" >
<div class="form-group">
<input type="text" id="body"/>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Send" />
</div>
</form>
@endsection
@section('script')
<script>
var socket = io('http://localhost:3000');
socket.removeAllListeners(`private-chat-channel.{{$chatid}}.{{auth()->user()->id}}:App\\Events\\ChatEvent`);
socket.on(`private-chat-channel.{{$chatid}}.{{auth()->user()->id}}:App\\Events\\ChatEvent` , function(msg){
//console.log(msg);
$('#msgs').append(`<p><em><b>${msg.data.fromusername}</b></em> : ${msg.data.body}</p><hr>`)
});
$('#chatform').submit(function(e) {
e.preventDefault();
var body = $('#body').val();
var chatid ={{$chatid}} ;
axios.post('/store-message' , {
body:body,
chatid:chatid
}).then( function(response){
console.log(response);
var message=response;
socket.removeAllListeners(`private-message-channel.${message.data.from}.${message.data.to}:App\\Events\\MessageEvent`);
socket.on(`private-message-channel.${message.data.from}.${message.data.to}:App\\Events\\MessageEvent` , function(msg) {
console.log(msg);
$('#msgs').append(`<p><em><b>${msg.data.fromusername}</b></em> : ${msg.data.body}</p><hr>`);
$('#body').val('');
});
}).catch(function(error){
socket.removeAllListeners(`private-error-channel.{{auth()->user()->id}}:App\\Events\\ErrorMessage`);
socket.on(`private-error-channel.{{auth()->user()->id}}:App\\Events\\ErrorMessage` , function(msg){
console.log(msg);
});
console.error(error);
});
})
</script>
@endsection
聊天控制器中的 store_message
方法
public function store_message(Request $request)
{
$validator = Validator::make($request->all() , [
'chatid' => 'required',
'body' => 'required'
]);
if($validator->fails())
{
event(new ErrorMessage( auth()->user() ,$validator->errors()));
return response()->json(['errors' => $validator->errors()] , 400);
}
//dd($request);
if(!Chat::find($request->input('chatid')))
{
event(new ErrorMessage( auth()->user() ,'chat not found'));
return response()->json(['error'=>'error chat not found'] , 400);
}
$chat = Chat::find($request->chatid);
if($chat['user1_id'] == auth()->user()->id)
{
$to = $chat['user2_id'];
} elseif($chat['user2_id'] == auth()->user()->id)
{
$to = $chat['user1_id'];
}
//dd($to);
$message = new Message;
$message->chat_id = $request->chatid;
$message->from = auth()->user()->id;
$message->to = $to;
$message->fromusername= auth()->user()->name;
$message->tousername = User::find($to)->name;
$message->body = $request->body;
$message->save();
event(new MessageEvent(auth()->user() , $message));
event(new ChatEvent($request->chatid , $to ,$message));
return $message;
}
MessageEvent.php
<?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;
use App\User;
class MessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $data;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user , $data )
{
$this->data = $data;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('message-channel.'.$this->user->id.'.'.$this->data->to);
}
}
ErrorEvent.php
<?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;
use App\User;
class ErrorMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $data;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user , $data)
{
$this->user = $user;
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('error-channel.'.$this->user->id);
}
}