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

如何用Laravel+Socket.io实现跨页面的实时事件推送与同步?

Laravel 掷骰子游戏跨页面实时同步实现方案

骰子页面截图

技术选型

跨页面实时同步依赖服务端主动推送,Laravel生态优先用原生工具栈实现,无需引入冗余第三方服务:

  • 服务端推送用 Laravel Reverb,Laravel 10+ 版本官方原生支持的WebSocket服务,无需额外部署Node.js服务
  • 前端监听用 Laravel Echo 配合原生JS实现,适配所有页面的公共逻辑

具体实现步骤

1. 服务端配置

  • 安装Reverb依赖:
    composer require laravel/reverb --with-all-dependencies
  • 自动生成配置项:
    php artisan reverb:install
  • 修改.env配置,设置广播驱动为Reverb:
    BROADCAST_CONNECTION=reverb
  • 新建骰子状态广播事件:
    php artisan make:event DiceStateUpdated
    编辑事件类,实现公共频道广播逻辑:
// app/Events/DiceStateUpdated.php
namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PublicChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class DiceStateUpdated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public function __construct(
        public string $state, // rolling=转动中 finished=转动结束
        public int $diceValue, // 最终点数,转动中传0即可
        public int $timestamp = 0
    )
    {
        $this->timestamp = now()->timestamp;
    }

    public function broadcastOn(): Channel
    {
        return new PublicChannel('dice-game');
    }
}

2. 掷骰子接口逻辑改造

在原有的掷骰子请求接口中,分两次广播事件,同步状态到所有页面:

// routes/web.php 或 routes/api.php
Route::post('/roll-dice', function () {
    // 广播转动开始事件,触发所有页面的转动动画
    event(new DiceStateUpdated('rolling', 0));

    // 等待时长和前端骰子动画时长对齐,这里设1.5秒
    usleep(1500000);

    // 生成随机点数
    $finalValue = rand(1, 6);

    // 广播转动结束事件,同步最终点数到所有页面
    event(new DiceStateUpdated('finished', $finalValue));

    return response()->json(['dice_value' => $finalValue]);
});

3. 前端全局监听配置

在站点所有页面引入的公共JS文件中,配置Laravel Echo并全局监听广播事件:

// 公共JS文件,比如 resources/js/app.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;
window.Echo = new Echo({
    broadcaster: 'reverb',
    key: import.meta.env.VITE_REVERB_APP_KEY,
    wsHost: import.meta.env.VITE_REVERB_HOST,
    wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
    wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});

// 全局监听骰子状态事件
window.Echo.channel('dice-game')
    .listen('DiceStateUpdated', (event) => {
        if(event.state === 'rolling') {
            // 调用当前页面封装的骰子转动动画方法
            startDiceAnimation();
        } else if(event.state === 'finished') {
            // 停止转动动画,展示最终点数
            stopDiceAnimation(event.diceValue);
        }
    });

注意:如果前端收不到广播事件,可以在事件类中添加自定义事件名的方法:

public function broadcastAs(): string
{
    return 'dice.state.update';
}

前端监听时事件名前加.即可:.listen('.dice.state.update', () => {})

4. 运行部署

  • 本地调试时启动Reverb服务:php artisan reverb:start
  • 正式上线用Supervisor守护Reverb进程即可,配置规则和Laravel队列的守护规则一致。

轻量备选方案(无WebSocket)

如果站点访问量不大,不想额外维护WebSocket服务,可以用短轮询方案实现:

  • 服务端把最新的骰子状态、点数、更新时间戳存在Redis缓存中
  • 所有页面每隔1秒请求一次通用接口拉取最新状态,和本地存储的时间戳对比,有更新就触发对应动画和展示
    该方案实现成本更低,1秒的延迟对于掷骰子游戏的体验几乎没有影响。

内容的提问来源于stack exchange,提问作者Maulik Chodvadiya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:18:00