如何解决数据库存储的测验结束时间与前端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
相关产品推荐
相关产品推荐

