为何激活密钥相关函数的循环频率超过每秒一次?
激活密钥循环生成异常修复方案
你的问题根源有两个:一是密钥过期后立刻请求新密钥,容易因为客户端与服务器的时间差,导致新密钥刚拿到就被误判为过期,陷入无限请求循环;二是原代码没清理旧定时器,多个定时器叠加运行会搞乱逻辑。
下面是修复后的完整代码:
let countdownTimer = null; // 保存定时器引用,用于清理 async function getActivationToken() { // 先清掉之前的定时器,避免多个定时器同时跑 if (countdownTimer) { clearInterval(countdownTimer); countdownTimer = null; } try { const response = await fetch(`/api/user/activate`, { headers: {"Authorization": token} }); const json = await response.json(); // 延迟1秒再处理新密钥,解决时间差导致的误判 setTimeout(() => setActivationText(json), 1000); } catch (err) { console.error('获取激活密钥失败:', err); // 请求失败3秒后重试 setTimeout(getActivationToken, 3000); } } function setActivationText(json) { const activationEl = document.getElementById("activation-key"); const currentTime = Math.trunc(Date.now() / 1000); let timeLeft = json.data.expires - currentTime; // 处理时间差导致的负数情况,直接重新请求 if (timeLeft < 0) { activationEl.innerHTML = ` <h1 class="text-xl">Your activation key is: <span class="text-green-500">Loading...</span></h1> <h1 class="text-xl">This key will expire in <span class="text-green-500">Loading...</span></h1> `; return getActivationToken(); } // 更新初始显示内容 activationEl.innerHTML = ` <h1 class="text-xl">Your activation key is: <span class="text-green-500">${json.data.activation}</span></h1> <h1 class="text-xl">This key will expire <span class="text-green-500">in ${secondsToMinutesAndSeconds(timeLeft)}</span></h1> `; // 每秒更新倒计时,同时监控过期时间 countdownTimer = setInterval(() => { timeLeft--; if (timeLeft <= 0) { clearInterval(countdownTimer); // 过期后再请求新密钥 getActivationToken(); } else { // 实时更新倒计时文本 activationEl.innerHTML = ` <h1 class="text-xl">Your activation key is: <span class="text-green-500">${json.data.activation}</span></h1> <h1 class="text-xl">This key will expire <span class="text-green-500">in ${secondsToMinutesAndSeconds(timeLeft)}</span></h1> `; } }, 1000); } // 初始化启动 getActivationToken();
核心修复点:
- 定时器生命周期管理:每次请求新密钥前清除旧定时器,避免多个定时器叠加导致的倒计时混乱和频繁请求。
- 时间差缓冲:新密钥获取后延迟1秒再处理,避免客户端与服务器时间不同步,导致新密钥刚生成就被判定为过期。
- 优化倒计时逻辑:不再递归调用
setActivationText,而是在定时器内部直接更新倒计时,逻辑更清晰,也避免了不必要的函数调用。 - 异常处理:增加请求失败的捕获和重试机制,提升代码稳定性。
内容的提问来源于stack exchange,提问作者Johnodon
相关产品推荐
相关产品推荐

