本文目录导读:

在Laravel中,实现实时进度更新推荐使用WebSocket,但并非必须,以下是详细的方案对比和实现建议:
为什么推荐WebSocket?
实时性要求
- WebSocket:全双工通信,服务器可主动推送进度数据
- HTTP轮询:需要客户端反复请求,延迟高且浪费资源
典型场景
- 文件上传/处理进度
- 长时间运行的任务(导出、批量操作)
- 实时数据同步
Laravel中的WebSocket方案
Laravel Reverb(推荐,Laravel 10+)
// 1. 安装
composer require laravel/reverb
// 2. 配置广播
// config/broadcasting.php
'connections' => [
'reverb' => [
'driver' => 'reverb',
'key' => env('REVERB_APP_KEY'),
'secret' => env('REVERB_APP_SECRET'),
'app_id' => env('REVERB_APP_ID'),
'options' => [
'host' => env('REVERB_HOST'),
'port' => env('REVERB_PORT'),
],
],
],
// 3. 创建事件
php artisan make:event TaskProgress
// 4. 事件类
class TaskProgress implements ShouldBroadcast
{
public $progress;
public $taskId;
public function __construct($taskId, $progress)
{
$this->taskId = $taskId;
$this->progress = $progress;
}
public function broadcastOn()
{
return new Channel('task.'.$this->taskId);
}
}
// 5. 触发更新
event(new TaskProgress($taskId, 50));
Laravel WebSockets(第三方包)
composer require beyondcode/laravel-websockets
Pusher(第三方服务)
// .env PUSHER_APP_ID=your-app-id PUSHER_APP_KEY=your-key PUSHER_APP_SECRET=your-secret PUSHER_APP_CLUSTER=mt1 // 使用 event(new TaskProgress($taskId, 75));
不使用WebSocket的备选方案
Server-Sent Events (SSE)
// 路由
Route::get('/progress/{taskId}', function ($taskId) {
return response()->stream(function () use ($taskId) {
while (true) {
$progress = Cache::get("task_$taskId", 0);
echo "data: $progress\n\n";
ob_flush();
flush();
if ($progress >= 100) break;
usleep(500000); // 0.5秒
}
}, 200, [
'Content-Type' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'Connection' => 'keep-alive',
]);
});
HTTP轮询(简单但不推荐)
// 前端每2秒查询一次
setInterval(async () => {
const response = await fetch(`/api/task/${taskId}/progress`);
const data = await response.json();
updateProgress(data.progress);
}, 2000);
实际应用示例:文件上传进度
HTML + JavaScript
<!-- 使用Socket.IO客户端 -->
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
<script>
const socket = io('http://localhost:8080');
// 监听进度更新
socket.on('upload.progress', (data) => {
const progressBar = document.getElementById('progress');
progressBar.style.width = data.percent + '%';
progressBar.textContent = data.percent + '%';
});
// 上传文件
async function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
}
</script>
Laravel后端
// 控制器
class UploadController extends Controller
{
public function upload(Request $request)
{
$file = $request->file('file');
$taskId = uniqid();
// 模拟长时间处理
for ($i = 0; $i <= 100; $i += 10) {
sleep(1); // 模拟处理时间
// 广播进度
broadcast(new TaskProgress($taskId, $i));
}
return response()->json(['taskId' => $taskId]);
}
}
决策建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 新项目(Laravel 10+) | Reverb | 官方支持,性能好,易于集成 |
| 已有Pusher账号 | Pusher | 节省服务器资源,无需维护 |
| 简单进度展示 | SSE | 实现简单,无需额外服务 |
| 实时性要求不高 | 轮询 | 最简方案,但效率低 |
最佳实践
- 小规模应用:使用Reverb + Laravel Echo
- 高并发场景:考虑Redis + WebSocket集群
- 移动端优化:WebSocket比轮询省电90%
- 安全性:使用Laravel认证中间件保护WebSocket连接
对于实时进度更新,WebSocket是最优选择,Laravel Reverb提供了开箱即用的解决方案,推荐在新项目中使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播