我正在尝试为我的网络应用程序编写一个简单的实时应用程序。我尝试用简单的 php/blade 对其进行编码(使用 Pusher Cdn),程序给出了预期的结果:提交表单时,广播一个新事件,另一个客户端接收消息。当我突然在 Inertia 中尝试它(使用 Laravel-Echo)时,它开始做一些奇怪的事情,例如只需单击一下即可渲染(多次)接收器部分。
Pusher Cdn 和 PHP/Blade:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body class="font-sans antialiased">
<div className="grid place-items-center">
<h1 className="text-slate-800 text-center p-8 text-7xl font-bold uppercase">
Test Page
</h1>
<p className="text-slate-500 px-8 text-center mt-3 text-2xl font-bold">
This page is dedicated to test a Real Time Chat in React,
using Laravel Echo and Pusher. Request will be done using
Jquery
</p>
<form>
<button
id='btn'
className="mt-8 text-center border border-slate-800 bg-slate-800 text-white font-bold text-2xl p-3 rounded"
>
Broadcast
</button>
</form>
</div>
<div className="mt-48 grid place-items-center">
<span id="placeholder"></span>
</div>
</body>
<script>
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
const pusher = new Pusher("{{ config('broadcasting.connections.pusher.key') }}", {cluster: "eu"});
const channel = pusher.subscribe('public');
channel.bind('chat', function(data){
$.post('/receive', {
_token: '{{csrf_token()}}',
message: "Hello, From JS",
}).done(res => $("#placeholder").last().after(res));
});
$("form").submit(function(e){
e.preventDefault();
$.ajax({
url: '/broadcast',
method:"POST",
headers: {
"X-Socket-Id": pusher.connection.socket_id
},
data: {
_token: "{{ csrf_token() }}",
message: "Hello,From JS"
}
}).done(res => $("#placeholder").last().after(res));
})
</script>
</html>
Inertia(React)和 Laravel-Echo:
import React from "react";
import $ from "jquery";
import Echo from "laravel-echo";
import Pusher from "pusher-js";
import { CSRF_TOKEN } from "@/Utils/forms";
function Test() {
window.Pusher = Pusher;
window.Pusher.logToConsole = true;
window.Echo = new Echo({
broadcaster: "pusher",
key: "c804af4b0e3beefe4880",
cluster: "eu",
});
window.Echo.channel("public").listen(".chat", function (data) {
$.post("/receive", {
_token: `${CSRF_TOKEN}`,
message: "Hello, From JS",
}).done((res) => $("#placeholder").last().after(res));
});
const handleSubmit = (e) => {
e.preventDefault();
$.ajax({
url: "/broadcast",
method: "POST",
headers: {
"X-Socket-Id": window.Echo.socketId(),
},
data: {
_token: CSRF_TOKEN,
message: "Hello, From JS",
},
}).done((res) => $("#placeholder").last().after(res));
};
return (
<>
<div className="grid place-items-center">
<h1 className="text-slate-500 text-center p-8 text-7xl font-bold uppercase">
Test Page
</h1>
<p className="text-slate-300 px-8 text-center mt-3 text-2xl font-bold">
This page is dedicated to test a Real Time Chat in React,
using Laravel Echo and Pusher. Request will be done using
Jquery
</p>
<form onSubmit={handleSubmit}>
<button
type="submit"
className="mt-8 text-center border border-slate-800 bg-slate-800 text-white font-bold text-2xl p-3 rounded"
>
Broadcast
</button>
</form>
</div>
<div className="mt-48 grid place-items-center">
<span id="placeholder"></span>
</div>
</>
);
}
export default Test;
请原谅我乱七八糟的代码。正如我上面所说,该问题仅在使用 Laravel-Echo 时出现
Expected results:
Client 1: Hello,From JS broadcast
Client 2: Hello, From JS receiver
Actual Results:
Client 1: Hello, From JS receiver; Hello,From JS broadcast
Client 2: Hello, From JS receiver; Hello, From JS receiver
好吧,我正在发布为我解决的问题,以防其他开发人员遇到同样的问题。
useEffect(() => {
window.Pusher = Pusher;
window.Pusher.logToConsole = true;
window.Echo = new Echo({
broadcaster: "pusher",
key: "c804af4b0e3beefe4880",
cluster: "eu",
});
const channel = window.Echo.channel("public");
channel.listen(".chat", function (data) {
$.post("/receive", {
_token: `${CSRF_TOKEN}`,
message: "Hello, From JS",
}).done((res) => $("#placeholder").last().after(res));
});
return () => {
// Cleanup when the component unmounts
channel.unbind(".chat");
};
}, []);
const handleSubmit = (e) => {
e.preventDefault();
$.ajax({
url: "/broadcast",
method: "POST",
headers: {
"X-Socket-Id": window.Echo.socketId(),
},
data: {
_token: CSRF_TOKEN,
message: "Hello, From JS",
},
}).done((res) => $("#placeholder").last().after(res));
};
我本质上所做的是将负责设置推送器并侦听 useEffect 函数中事件的代码放在一个空数组中。我使用 useEffect 挂钩来确保我们在组件加载时仅设置事件侦听器一次。为了保持整洁,我在 return 语句中添加了一个清理函数