队列任务进度实时推送需任务执行时写redis状态并广播事件,前端通过websocket订阅接收,而非dispatch()直接推送;须配置laravelwebsockets为pusher驱动、使用public频道、前端先查初始进度并校验连接与命名一致性。

队列任务里怎么把进度发给前端
不能靠 Laravel 自带的 dispatch() 直接推——它只管把任务扔进队列,不负责状态同步。真要实时推送进度,得让任务自己“说话”:执行中主动写状态、前端主动或被动收消息。核心是拆成两件事:任务侧存进度,前端侧连 WebSocket 拿更新。
- 推荐用 Redis 的
SET或HSET存进度,键名建议含任务 ID(如job:progress:{uuid}),避免冲突 - 别用数据库主表存进度——高频率
UPDATE会拖慢队列消费,尤其并发多时 - 前端不要轮询
/api/progress/{id},HTTP 轮询延迟高、连接浪费,WebSocket 是更直接的路径
Laravel + LaravelWebSockets 怎么让任务触发通知
关键在任务执行时调用 event() 或直接用 broadcast(),但必须确保广播驱动配对、频道可公开订阅。LaravelWebSockets 默认只处理 pusher 协议广播,所以 BROADCAST_DRIVER=redis 不行,得切到 pusher 并配好 PUSHER_APP_ID 等环境变量,让它把事件转给 WebSocket 服务。
- 任务里用
broadcast(new JobProgressUpdated($jobId, $percent)),事件类需实现ShouldBroadcast - 频道必须是 public 类型(如
ProgressChannel中返回truefromjoin()),private/channel 不被前端直连 - 前端用
echo.channel('progress.' + jobId)订阅,频道名要和事件广播的完全一致 - 如果用
redis驱动+自定义监听器推 WebSocket,容易漏掉重连逻辑,不如走标准广播链路稳
为什么任务刚 dispatch 就收不到第一条进度
因为广播发生在任务真正执行时,不是分发时。dispatch() 只把任务塞进 Redis 队列,Worker 还没捞起来,自然没进度、没广播。常见错觉是“发了就该有”,其实是时间差问题。
- 前端订阅频道后,应先查一次当前进度(比如 GET
/api/job/{id}/progress),补上初始状态 - 任务开头立刻写一次
1%到 Redis,并广播,避免前端等半天没动静 - Worker 进程如果卡住(比如内存溢出、死锁),进度就停在那——加个超时检测和失败回调,比等前端问“怎么不动了”更主动
前端收到消息但页面没更新?检查这三处
90% 是频道名拼错、事件名不匹配、或 LaravelWebSockets 服务没跑起来。别急着改 Vue/React 逻辑,先确认底层通路是否真实打通。
- 用
php artisan websocket:serve启动后,访问http://localhost:6001/laravel-websockets看面板有没有连接数、有没有频道列表 - 浏览器控制台看 Echo 是否报
Connection refused或404 on /laravel-websockets,对应检查BROADCASTING_URL和 Nginx 反代配置 - 事件名默认是类全名(如
App\Events\JobProgressUpdated),前端监听时得写全,或者在事件里覆盖broadcastAs()方法简化
进度推送看着简单,实际卡点都在“谁在什么时候写了什么、谁又在什么时候读到了”。中间任何一环断开——Redis 过期、Worker 崩溃、WebSocket 断连未重连、前端频道名少个点——都会让进度停在 5%,而你还在翻 JS 控制台。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











