You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9异步Job执行时如何实时推送NoticeEvent通知?

Laravel 9队列任务实时推送Pusher进度通知方案

问题背景

在Laravel 9中实现了处理大量图片的ExchangeJob队列任务,通过NoticeEvent结合Pusher推送处理进度,但所有事件会被暂存至Job完成后才批量触发,无法实时接收进度通知。

相关代码

ExchangeJob类

class ExchangeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct()
    {
       
    }

    public function handle()
    {
        $ImageObject = new \App\Core\Images;
        $ImageObject->ProductsImagesRegenerate();
    }
}

ProductsImagesRegenerate方法

public function ProductsImagesRegenerate(): void {
    NoticeEvent::dispatch('Starting processing notice');

    $images = array("red", "green", "blue", "yellow");
    
    foreach ($images as $value) {
        NoticeEvent::dispatch($value);
    }

    event(new NoticeEvent("End processing images"));
}

日志现象
执行php artisan queue:listen后,NoticeEvent全部在ExchangeJob完成后才执行:

2022-12-10 20:45:41 App\Jobs\ExchangeJob ........................... RUNNING
2022-12-10 20:45:55 App\Jobs\ExchangeJob .................. 13,073.61ms DONE
2022-12-10 20:45:55 App\Events\NoticeEvent ......................... RUNNING
2022-12-10 20:45:55 App\Events\NoticeEvent ................... 333.14ms DONE
...

解决方案

1. 配置事件监听器为异步队列

让NoticeEvent的监听器进入独立队列,确保事件能被即时消费:

  • 修改app/Providers/EventServiceProvider.php,注册事件与监听器:
protected $listen = [
    \App\Events\NoticeEvent::class => [
        \App\Listeners\NoticeEventListener::class,
    ],
];
  • 让监听器实现ShouldQueue接口,支持队列异步处理:
namespace App\Listeners;

use App\Events\NoticeEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Pusher\Pusher;

class NoticeEventListener implements ShouldQueue
{
    // 可指定专属队列,优先处理通知
    public $queue = 'notifications';

    public function handle(NoticeEvent $event)
    {
        // 执行Pusher推送逻辑
        $pusher = new Pusher(
            config('broadcasting.connections.pusher.key'),
            config('broadcasting.connections.pusher.secret'),
            config('broadcasting.connections.pusher.app_id'),
            config('broadcasting.connections.pusher.options')
        );

        $pusher->trigger('progress-channel', 'notice-event', [
            'message' => $event->message
        ]);
    }
}

2. 调整事件分发方式

使用dispatchAfterResponse确保事件无需等待当前Job进程即可触发:

public function ProductsImagesRegenerate(): void {
    NoticeEvent::dispatchAfterResponse('Starting processing notice');

    $images = array("red", "green", "blue", "yellow");
    
    foreach ($images as $value) {
        NoticeEvent::dispatchAfterResponse($value);
    }

    NoticeEvent::dispatchAfterResponse("End processing images");
}

3. 检查队列核心配置

  • 确保.env中队列驱动非sync(建议用redis或database):
QUEUE_CONNECTION=redis
  • 启动队列监听时,优先处理通知队列:
php artisan queue:listen --queue=notifications,default

4. 避免事务阻塞

若Job中包含数据库事务,需将事件分发放在事务外部,或使用DB::afterCommit确保事务提交后触发事件(如果业务允许):

// 事务内处理图片逻辑
DB::transaction(function () {
    // 图片处理操作
});

// 事务外分发进度事件
NoticeEvent::dispatch('当前批次处理完成');

内容的提问来源于stack exchange,提问作者Александр Инженер

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:50:33