如何用JavaScript回调实现顺序触发的多倒计时器且跨窗口结果一致
嘿,我来帮你搞定这个按顺序触发的倒计时器!先看看你现有代码里的几个小问题,再给你一个更简洁、可复用的实现方案~
先说说你代码里的问题
- 函数调用错误:你用了
new y()和new z()来调用函数,这是构造函数的实例化写法,普通函数直接写y()、z()就行,不然会创建一个不必要的对象实例,还可能导致逻辑不执行。 - 第二个倒计时没启动定时器:你的
y函数只是定义了计算逻辑,但没有像x那样用setInterval每秒更新,所以它只会执行一次,不会动态刷新倒计时。 - 代码重复冗余:两个倒计时的时间计算、DOM更新逻辑几乎完全一样,重复写不仅麻烦,后期维护也容易出错。
优化后的实现方案
我们可以封装一个通用的倒计时函数,把重复逻辑抽出来,然后通过回调函数实现“上一个结束就启动下一个”的顺序触发逻辑。这样不管你要加多少个倒计时,都能轻松扩展。
完整代码
<p id="demo"></p> <p id="demo12"></p> <p id="demo123"></p> <script> // 封装通用倒计时函数 function createCountdown(targetTimestamp, displayId, onFinish) { // 启动定时器,保存ID用于后续清除 const timer = setInterval(() => { const now = new Date().getTime(); const distance = targetTimestamp - now; // 计算天、时、分、秒 const days = Math.floor(distance / (1000 * 60 * 60 * 24)); const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((distance % (1000 * 60)) / 1000); // 更新DOM显示 document.getElementById(displayId).innerHTML = `${days}d ${hours}h ${minutes}m ${seconds}s `; // 倒计时结束处理 if (distance < 0) { clearInterval(timer); document.getElementById(displayId).innerHTML = "EXPIRED"; // 执行结束后的回调(如果有的话) if (onFinish) onFinish(); } }, 1000); } // 定义所有倒计时的目标时间(用getTime转成时间戳,计算更高效) const countdowns = [ { target: new Date("Jan 6, 2018 11:42:00").getTime(), display: "demo" }, { target: new Date("Jan 6, 2018 11:42:25").getTime(), display: "demo12" }, { target: new Date("Jan 6, 2018 11:42:30").getTime(), display: "demo123" } ]; // 递归触发下一个倒计时的函数 function startNextCountdown(index) { if (index >= countdowns.length) return; // 所有倒计时都完成了,退出 const current = countdowns[index]; createCountdown(current.target, current.display, () => { // 当前倒计时结束后,启动下一个 startNextCountdown(index + 1); }); } // 启动第一个倒计时 startNextCountdown(0); // 你原来的z函数可以放在这里,比如第三个倒计时结束后执行 // function z() { // alert('所有倒计时都结束啦!'); // } // 可以在countdowns数组最后一项的onFinish里调用它 </script>
关键说明
- 通用函数复用:
createCountdown函数把倒计时的核心逻辑都封装起来,每次只需要传入目标时间戳、显示元素ID和结束回调,避免重复代码。 - 顺序触发逻辑:用
startNextCountdown递归函数,当前一个倒计时的onFinish回调触发时,自动启动下一个倒计时,完美实现你要的“依次启动”需求。 - 一致性保证:你用固定的目标时间来计算倒计时,这点非常正确——不管用户什么时候打开页面,都是基于当前时间和固定目标时间的差值计算,所以不同窗口显示的倒计时进度是完全一致的。
- 定时器清理:每个倒计时结束时都会用
clearInterval清除定时器,避免不必要的内存消耗。
如果需要在最后一个倒计时结束后执行额外逻辑(比如你原来的z函数),只需要在countdowns最后一项的回调里调用它就行啦~
内容的提问来源于stack exchange,提问作者Anupam Agnihotri
相关产品推荐
相关产品推荐

