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

如何解决数据库存储的测验结束时间与前端15秒答题倒计时不同步问题

答题倒计时时间一致性实现方案

核心思路

调整「存end_time」的触发时机,从用户触发开始答题的节点延后到前端页面加载完成、倒计时正式启动的节点,同时增加前后端时间偏移校准,避免网络延迟、本地定时器误差导致的时间不一致问题。

具体实现步骤

1. 调整后端接口逻辑

  • 拆分原有逻辑为两个接口:
    • 获取题目接口:用户点击开始答题后调用,仅返回题目内容、question_id、当前服务端时间戳,仅在quiz_attempts表插入user_id、question_id的初始记录,end_time字段留空
    • 确认开始答题接口:前端页面渲染完成、准备启动倒计时时调用,后端收到请求后用当前服务端时间+15秒作为end_time,更新到对应用户的quiz_attempts记录中,同时将end_time的时间戳返回给前端

2. 前端倒计时逻辑

  • 收到题目接口响应时记录本地时间戳receive_local_ts,计算服务端与本地的时间偏移量:time_offset = 服务端返回的当前时间戳 - receive_local_ts
  • 页面渲染完成后调用确认开始答题接口,拿到返回的end_time戳后启动倒计时:
    每秒计算一次当前服务端校准时间:current_server_ts = Date.now() + time_offset
    剩余答题时间:left_seconds = Math.ceil((end_time_ts * 1000 - current_server_ts) / 1000)
    将left_seconds直接渲染到<span class="counter"></span>节点即可,小于等于0时直接触发超时提交逻辑

3. 提交校验逻辑

用户提交答案时,后端直接用当前服务端时间与库中存储的end_time对比,超过end_time直接判定为超时,无需信任前端传递的任何时间参数,避免前端篡改作弊。

核心代码示例

前端核心逻辑

// 请求题目
fetch('/api/get-question', { method: 'POST' })
  .then(res => res.json())
  .then(data => {
    const receiveLocalTs = Date.now()
    const timeOffset = data.server_current_ts - receiveLocalTs
    // 渲染题目内容
    document.querySelector('.question-content').innerText = data.question_content
    // 确认开始答题
    return fetch('/api/confirm-start', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ question_id: data.question_id })
    }).then(res => res.json()).then(startRes => ({ startRes, timeOffset }))
  })
  .then(({ startRes, timeOffset }) => {
    const endTimeTs = startRes.end_time_ts
    // 启动倒计时
    const timer = setInterval(() => {
      const currentServerTs = Date.now() + timeOffset
      const leftSeconds = Math.ceil((endTimeTs * 1000 - currentServerTs) / 1000)
      document.querySelector('.counter').innerText = leftSeconds > 0 ? leftSeconds : 0
      if (leftSeconds <= 0) {
        clearInterval(timer)
        // 触发超时提交
        handleSubmit(true)
      }
    }, 1000)
  })

后端更新end_time逻辑(SQL示例)

UPDATE quiz_attempts 
SET end_time = FROM_UNIXTIME(UNIX_TIMESTAMP() + 15) 
WHERE user_id = [当前登录用户ID] AND question_id = [前端传递的题目ID]
LIMIT 1;

异常兼容

如果用户中途刷新页面,前端请求答题状态接口时,后端直接返回已存储的end_time,前端复用上述时间偏移校准逻辑计算剩余时间继续倒计时即可,不会出现时间错乱问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:36:04