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

如何在不刷新PHP页面的情况下追踪MySQL数据库的变更?

这需求太典型了——用户提交请求后,管理员操作要实时同步到用户页面,不用刷新。我之前做过类似的工单系统,给你整理几种落地的方案,从易到难,你可以根据项目规模选:

核心实现方案

1. 短轮询(最简单的入门方案)

原理就是前端每隔一段时间主动发请求去MySQL查最新状态,拿到结果后更新页面。优点是零后端额外配置,改改前端加个接口就行,适合小型项目。

前端代码示例(原生JS)

// 定义查询状态的函数
function checkRequestStatus(requestId) {
  fetch(`/api/get-request-status?requestId=${requestId}`)
    .then(res => res.json())
    .then(data => {
      const statusElement = document.getElementById(`status-${requestId}`);
      if (data.status !== statusElement.textContent) {
        // 更新状态文本,还可以加个样式变化提示用户
        statusElement.textContent = data.status;
        statusElement.style.color = data.status === '已接受' ? 'green' : 'orange';
      }
    })
    .catch(err => console.error('查询状态失败:', err));
}

// 每隔30秒查一次(时间可以根据需求调)
const requestId = '123'; // 这里替换成实际的请求ID
setInterval(() => checkRequestStatus(requestId), 30000);

后端接口示例(Node.js + Express + MySQL)

const express = require('express');
const mysql = require('mysql2/promise');
const app = express();

// 创建MySQL连接池
const pool = mysql.createPool({
  host: 'localhost',
  user: 'your_user',
  password: 'your_password',
  database: 'your_db'
});

// 状态查询接口
app.get('/api/get-request-status', async (req, res) => {
  const { requestId } = req.query;
  try {
    const [rows] = await pool.execute('SELECT status FROM service_requests WHERE id = ?', [requestId]);
    if (rows.length === 0) {
      return res.json({ status: '不存在' });
    }
    res.json({ status: rows[0].status });
  } catch (err) {
    res.status(500).json({ error: '查询失败' });
  }
});

app.listen(3000, () => console.log('服务启动'));

注意:短轮询的缺点是会产生很多无效请求(比如状态没变化的时候),如果用户量大会增加服务器压力,所以时间间隔别设太短。

2. 长轮询(比短轮询更高效)

原理是前端发请求后,后端不会立刻返回结果,而是hold住请求,直到数据库里的状态发生变化,或者超时(比如30秒)才返回。这样能减少请求次数,比短轮询高效很多。

前端代码示例

function longPollRequestStatus(requestId) {
  fetch(`/api/long-poll-status?requestId=${requestId}`)
    .then(res => res.json())
    .then(data => {
      // 更新页面状态
      const statusElement = document.getElementById(`status-${requestId}`);
      statusElement.textContent = data.status;
      statusElement.style.color = data.status === '已接受' ? 'green' : 'orange';
      // 请求返回后立刻发起下一次长轮询
      longPollRequestStatus(requestId);
    })
    .catch(err => {
      console.error('长轮询失败:', err);
      // 失败后延迟几秒再重试,避免频繁请求
      setTimeout(() => longPollRequestStatus(requestId), 5000);
    });
}

// 启动长轮询
const requestId = '123';
longPollRequestStatus(requestId);

后端接口示例(Node.js)

app.get('/api/long-poll-status', async (req, res) => {
  const { requestId } = req.query;
  let intervalId;

  // 定时查询数据库,直到状态变化或超时
  const checkStatus = async () => {
    const [rows] = await pool.execute('SELECT status FROM service_requests WHERE id = ?', [requestId]);
    const currentStatus = rows[0]?.status;

    // 如果状态不是待处理,就返回结果
    if (currentStatus !== '待处理') {
      clearInterval(intervalId);
      res.json({ status: currentStatus });
    }
  };

  // 每隔2秒查一次数据库
  intervalId = setInterval(checkStatus, 2000);

  // 设置30秒超时,避免请求一直挂着
  setTimeout(() => {
    clearInterval(intervalId);
    res.json({ status: '待处理' }); // 返回当前状态,前端继续轮询
  }, 30000);

  // 监听客户端断开连接,清理定时器
  req.on('close', () => {
    clearInterval(intervalId);
  });
});

3. WebSocket(实时性最强,推荐复杂场景)

如果你的项目实时性要求很高(比如管理员操作后用户页面要立刻更新),WebSocket是最佳选择。它是双向通信协议,后端可以主动给前端推送消息,不用前端反复请求。

前端代码示例

// 建立WebSocket连接
const ws = new WebSocket(`ws://localhost:3000/ws?requestId=123`);

// 连接成功
ws.onopen = () => {
  console.log('WebSocket连接成功');
};

// 接收后端推送的消息
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  const statusElement = document.getElementById(`status-${data.requestId}`);
  statusElement.textContent = data.status;
  statusElement.style.color = data.status === '已接受' ? 'green' : 'orange';
};

// 连接关闭时重连
ws.onclose = () => {
  setTimeout(() => window.location.reload(), 5000); // 或者重新创建连接
};

后端示例(Node.js + ws库 + MySQL)

首先安装ws库:npm install ws

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });

// 存储连接的客户端,key是requestId
const clients = new Map();

wss.on('connection', (ws, req) => {
  const urlParams = new URLSearchParams(req.url.slice(1));
  const requestId = urlParams.get('requestId');

  // 将客户端连接和requestId关联
  if (requestId) {
    if (!clients.has(requestId)) {
      clients.set(requestId, []);
    }
    clients.get(requestId).push(ws);
  }

  // 客户端断开连接时移除
  ws.on('close', () => {
    if (requestId && clients.has(requestId)) {
      clients.set(requestId, clients.get(requestId).filter(client => client !== ws));
      if (clients.get(requestId).length === 0) {
        clients.delete(requestId);
      }
    }
  });
});

// 当管理员更新状态时,推送消息给对应客户端
app.post('/api/update-request-status', async (req, res) => {
  const { requestId, status } = req.body;
  try {
    await pool.execute('UPDATE service_requests SET status = ? WHERE id = ?', [status, requestId]);
    // 推送给所有关注这个requestId的客户端
    if (clients.has(requestId)) {
      clients.get(requestId).forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
          client.send(JSON.stringify({ requestId, status }));
        }
      });
    }
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: '更新失败' });
  }
});
方案选择建议
  • 小型项目/需求简单:用短轮询,开发快,成本低。
  • 中型项目/想减少请求:用长轮询,比短轮询高效,又不用改太多架构。
  • 大型项目/高实时性要求:用WebSocket,体验最好,适合频繁更新的场景。

内容的提问来源于stack exchange,提问作者Pavan Kumar Lekkala

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:04:10