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

基于Cookie的JS倒计时页面刷新后时间回跳问题排查

刷新页面后倒计时数值偏大问题修复

问题根因

所有问题均来自时间计算的单位错误和逻辑设计缺陷:

  • 剩余时长计算单位不匹配
    原代码计算初始剩余时间的逻辑为:
    var timing = 60 * (60 * 24 -(Date.now() - getCookie('timer')) / 3600 / 24)
    
    Date.now()和Cookie中存储的值都是毫秒级时间戳,原代码做差值后没有先除以1000转换为秒,直接除以3600、24做时间换算,得到的数值远大于实际剩余秒数,这就是刷新后时间偏大的核心原因。
  • 重置逻辑阈值错误
    原代码判断时间差超过60*24天(1440天)才重置Cookie,但Cookie本身设置的max-age只有1天,该判断完全不生效。
  • 计时逻辑存在固有缺陷
    原逻辑在页面加载时记录start时间点,后续仅基于该时间点计算本次打开页面后的流逝时间,setInterval本身的触发延迟会逐步累积误差;倒计时归零时仅修改start变量,没有同步更新Cookie,会导致后续刷新后计时完全错乱。

修复后完整代码

注:保留了原代码中适配SO代码片段的cookieStore兼容逻辑,生产环境可按需移除

// 总倒计时时长:1天,单位秒
const TOTAL_DURATION = 24 * 60 * 60;
const COOKIE_MAX_AGE = 24 * 60 * 60;

function startTimer(display) {
    function timer() {
        const timerCookie = getCookie('timer');
        // 直接基于Cookie存储的初始时间戳计算剩余值,避免setInterval累积误差
        const elapsedSecond = Math.floor((Date.now() - Number(timerCookie)) / 1000);
        let diff = TOTAL_DURATION - elapsedSecond;

        // 倒计时归零,重置Cookie
        if (diff <= 0) {
            setCookie('timer', Date.now());
            diff = TOTAL_DURATION;
        }

        const hours = String(Math.floor((diff / 3600) % 24)).padStart(2, '0');
        const minutes = String(Math.floor((diff / 60) % 60)).padStart(2, '0');
        const seconds = String(diff % 60).padStart(2, '0');

        display.textContent = `${hours}:${minutes}:${seconds}`;
    }
    timer();
    setInterval(timer, 1000);
}

window.cookieStore ||= {};
function getCookie(name) {
    try {
        const match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
        return match ? match[1] : null;
    } catch (err) {
        return window.cookieStore[name];
    }
}

function setCookie(name, value) {
    try {
        document.cookie = `${name}=${value}; max-age=${COOKIE_MAX_AGE}`;
    } catch (err) {
        window.cookieStore[name] = value;
    }
}

// 初始化Cookie:不存在或已过期时重置
const savedTimer = getCookie('timer');
if (!savedTimer || (Date.now() - Number(savedTimer))/1000 >= TOTAL_DURATION) {
    setCookie('timer', Date.now());
}

window.onload = function () {
    const display = document.querySelector('#time');
    startTimer(display);
};

对应HTML代码:

<div id="time"></div>

修复说明

  • 统一所有时间计算的单位:时间戳差值先除以1000转换为秒后再做后续运算,从根源解决数值偏大问题
  • 去掉startTimer中依赖页面加载时间点的start变量,每次执行计时函数时直接读取Cookie中的初始时间戳计算剩余值,完全避免setInterval触发延迟带来的累积误差,也不需要在页面加载时提前计算剩余时长
  • 修正重置逻辑:剩余时长归零时直接更新Cookie中的初始时间戳,重置判断阈值和Cookie过期时间保持一致,均为1天
  • 用padStart简化补零逻辑,代码可读性更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:24:20