You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

无需Node.js框架的WebSocket替代方案?投注游戏实时更新需求

实现投注游戏实时数据更新的方案

嘿,我来帮你梳理几个不用频繁Ajax轮询、也不用学新框架就能搞定实时更新的办法,完全适配你现有的jQuery/JS+MySQL技术栈!

首选方案:Server-Sent Events (SSE)

这绝对是最适合你的需求的方案——单向服务器推送,原生浏览器支持,不用引入任何新框架,代码轻量易维护。它的核心是前端和后端建立一个持久连接,服务器有新数据时主动推给前端,完美匹配你“投注信息进来时实时更新页面”的需求。

前端实现(原生JS或jQuery都能搞)

用原生EventSource就能轻松监听,甚至不用jQuery,不过如果习惯用jQuery也能封装:

// 原生SSE代码,简单直接
const betUpdates = new EventSource('/your-sse-endpoint.php');

// 收到新投注数据时更新页面
betUpdates.onmessage = function(event) {
  const newBet = JSON.parse(event.data);
  // 这里替换成你实际的页面更新逻辑,比如追加到投注列表
  $('#bet-history').prepend(`
    <div class="bet-item">
      <span class="user">${newBet.username}</span>
      <span class="amount">投注了 $${newBet.amount}</span>
      <span class="time">${newBet.created_at}</span>
    </div>
  `);
};

// 处理连接错误,比如自动重连
betUpdates.onerror = function(error) {
  console.warn('SSE连接中断,正在重试...');
  betUpdates.close();
  // 3秒后重新建立连接
  setTimeout(() => window.location.reload(), 3000);
};

后端实现(以PHP为例,适配你的MySQL)

后端只需要输出特定格式的响应,保持连接并循环查询最新投注:

<?php
// 设置SSE响应头
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *'); // 如果有跨域需求

// 连接你的MySQL数据库
$db = new mysqli('localhost', 'db-user', 'db-pass', 'your-db-name');
if ($db->connect_error) die('数据库连接失败');

// 记录最后一次获取的投注ID,避免重复推送
$lastBetId = 0;

// 持续监听新数据
while (true) {
    // 查询比上次ID更大的最新投注(按需调整SQL)
    $query = "SELECT * FROM bets WHERE id > {$lastBetId} ORDER BY id DESC LIMIT 1";
    $result = $db->query($query);

    if ($result->num_rows > 0) {
        $bet = $result->fetch_assoc();
        $lastBetId = $bet['id'];
        // 发送SSE格式的数据(必须以"data: "开头,结尾加两个换行)
        echo "data: " . json_encode($bet) . "\n\n";
        // 强制输出缓冲区内容
        ob_flush();
        flush();
    }

    // 每3秒查询一次,避免过度消耗数据库资源
    sleep(3);
}
?>

备选方案:长轮询(如果SSE不可用)

如果你的用户群体还在使用非常旧的浏览器(比如IE),SSE不支持的话,可以用长轮询——本质是Ajax的进阶版,但比普通定时轮询高效得多:前端发起请求后,后端会挂着连接直到有新数据返回,前端收到后立刻再发起下一次请求,避免了无效的空请求。

前端jQuery实现

function pollNewBets(lastId = 0) {
    $.ajax({
        url: '/long-poll-endpoint.php',
        type: 'GET',
        data: { last_id: lastId },
        timeout: 30000, // 30秒超时后自动重试
        success: function(response) {
            if (response.new_bet) {
                // 更新页面
                $('#bet-history').prepend(`<div class="bet-item">${response.new_bet.username} 投注了 $${response.new_bet.amount}</div>`);
                // 用最新的投注ID发起下一次请求
                pollNewBets(response.new_bet.id);
            } else {
                // 没有新数据,立刻重试
                pollNewBets(lastId);
            }
        },
        error: function() {
            // 请求出错,延迟5秒重试
            setTimeout(() => pollNewBets(lastId), 5000);
        }
    });
}

// 启动长轮询
pollNewBets();

后端PHP实现

<?php
header('Content-Type: application/json');
header('Cache-Control: no-cache');

$db = new mysqli('localhost', 'db-user', 'db-pass', 'your-db-name');
$lastBetId = isset($_GET['last_id']) ? (int)$_GET['last_id'] : 0;

// 最多等待30秒,期间循环查询新数据
$startTime = time();
while (time() - $startTime < 30) {
    $query = "SELECT * FROM bets WHERE id > {$lastBetId} ORDER BY id DESC LIMIT 1";
    $result = $db->query($query);

    if ($result->num_rows > 0) {
        echo json_encode(['new_bet' => $result->fetch_assoc()]);
        exit;
    }

    // 每秒查一次
    sleep(1);
}

// 超时返回无新数据
echo json_encode(['new_bet' => null]);
?>

关于WebSocket的误解:不是Node.js专属!

你之前看到的WebSocket方案大多基于Node.js,但其实所有后端语言都能实现WebSocket服务

  • PHP可以用Ratchet库搭建WebSocket服务
  • Python有Flask-SocketIO/Django Channels
  • Java可以用Tomcat自带的WebSocket支持

不过WebSocket是双向通信,如果你只需要服务器推投注更新,SSE已经足够;如果需要更复杂的互动(比如实时聊天、投注确认即时反馈),再考虑WebSocket也不迟。


内容的提问来源于stack exchange,提问作者Brett Kessler

火山引擎 最新活动