前端面试 P099:倒计时截止时间、漂移与完成事件
目前顯示中文(中國)原文
来源:方格前端讲面试 · 如何使用 js 实现一个支持设置 时间的倒计时器,并在倒计时结束时触发事件,13 分 49 秒。
回看定位:00:32 设计要点 · 07:15 扣减的原实现 · 12:41 完成事件
必须纠正:每次回调减固定间隔会漂移
课程的 setInterval 回调按 tickRate 扣减 remainingTime。后台、长任务或系统调度使回调晚到时,实际过了多久与扣掉多少不相同,倒计时会变慢。
对经过时长,可记录单调时钟截止点,每次根据 deadline - now 重新算;对服务端绝对截止时间,还应考虑服务端时间与客户端时钟偏差。
function startCountdown(durationMs, {
onTick = () => {}, onComplete = () => {},
now = () => performance.now(), interval = 250,
} = {}) {
if (!Number.isFinite(durationMs) || durationMs < 0 ||
!Number.isFinite(interval) || interval <= 0) throw new RangeError('Invalid time');
const deadline = now() + durationMs;
let timer = null, stopped = false;
function tick() {
if (stopped) return;
const remaining = Math.max(0, deadline - now());
onTick(remaining);
if (stopped) return;
if (remaining === 0) {
stopped = true;
onComplete();
} else timer = setTimeout(tick, Math.min(interval, remaining));
}
tick();
return () => { stopped = true; clearTimeout(timer); };
}
此版本立即报告一次,按真实经过时间计算,正常完成仅通知一次;返回清理函数。重置可先取消旧任务再建立新任务,暂停/恢复若需要保留剩余时长,应另外明确定义。
不承诺精准唤醒
时间到达时页面被冻结,完成回调只能等获得执行机会后运行,不能靠前端定时器准点执行交易、库存或权限逻辑。服务端时间判断仍是权威来源。
显示剩余秒可向上取整,结束时钳制到零;格式化与毫秒计算分开。回调异常、重复 start、重入、卸载清理和目标时间变化都需要验证。