我正在开发一个 Symfony 6 项目,在其中一个屏幕中,我想在按下按钮时开始执行 .jar。我已经设法异步执行它,但我无法通知客户端该过程已完成,因此我决定使用 websockets。我首先做了一个小设计来测试它们,由于某种原因,客户端只连接到网络服务器,但它不接收任何消息。
这是我的 JavaScript 文件
// WebSocket setup
const socket = new WebSocket('ws://localhost:8080');
socket.addEventListener('open', event => {
console.log('Connected');
});
socket.addEventListener('message', event => {
const message = JSON.parse(event.data);
if (message.type === 'progress') {
console.log(message.text);
}
});
socket.addEventListener('close', event => {
console.log('Connection closed');
});
// Fetch request
document.getElementById('upload-button').addEventListener('click', () => {
const fileInput = document.getElementById('zip-file');
const formData = new FormData(); // Create a new FormData object
formData.append('del-file', fileInput.files[0]); // Append the selected file to the FormData
fetch('/start-process', {
method: 'POST',
body: formData, // Send the FormData as the request body
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
});
这将是按下按钮时调用的函数
/**
* @Route("/start-process", name="start_process", methods={"POST"})
*/
public function startProcess(Request $request, MessageBusInterface $messageBus, WebSocketServer $webSocketServer): JsonResponse
{
// Start the asynchronous background job
$message = ['type' => 'progress', 'text' => 'Job started'];
$webSocketServer->broadcast(json_encode($message));
// Simulate background job
sleep(2); // Simulate work
$message = ['type' => 'progress', 'text' => 'Job in progress...'];
$webSocketServer->broadcast(json_encode($message));
sleep(2); // Simulate work
// Simulate background job completion
$message = ['type' => 'progress', 'text' => 'Job completed'];
$webSocketServer->broadcast(json_encode($message));
return $this->json(['message' => 'Process finished']);
}
我将其作为答案输入,因为它很长。
您在这里遇到的根本问题是您的 Websocket 是在与 Web 服务器不同的进程中打开的。如果您希望两者进行交互,则必须在同一进程中处理它们。这可能意味着混合这两个包,这样您就可以响应 websocket 请求和 Web 服务器请求。请注意,您需要某种方式将两者关联起来;您不能假设您只有一个客户端,因此您可能有多个 Web 套接字,您需要将它们分配给正确的 Web 会话。
请允许我针对您所讨论的内容提出替代策略。不要创建 Web 套接字,而是在前端使用 Javascript 循环,使用正常的
fetch
请求每秒左右轮询后端。然后,它就成为后端要处理的另一个 API,以返回操作的当前状态。
这是处理长时间运行的后台任务的一种非常常见的模式,并且比管理 Web 套接字简单得多。您甚至可以在线找到此代码。