⏰ JS中的两大定时器
setTimeout:一次性定时器(只执行一次)setInterval:循环定时器(每隔一段时间执行一次,直到手动停止)
⚠️ 注意 :时间单位都是毫秒!1 秒 = 1000 毫秒。
setTimeout:一次性定时器
等待指定时间后,只执行一次
js
// 写法1:直接写函数
setTimeout(function() {
// 这里写要执行的代码
}, 延迟时间(毫秒));
// 写法2:箭头函数(更简洁)
setTimeout(() => {
// 要执行的代码
}, 延迟时间);
// 3秒后弹出提示
setTimeout(() => {
alert('3秒到了!');
}, 3000);
// 5秒后把按钮文字改成"已过期"
const btn = document.getElementById('btn');
setTimeout(() => {
btn.innerText = '已过期';
btn.disabled = true;
}, 5000);
怎么清除它? clearTimeout
js
// 先把定时器存到一个变量里
const timer = setTimeout(() => {
alert('我不会执行了');
}, 3000);
// 点击按钮取消定时器
document.getElementById('cancelBtn').onclick = function() {
clearTimeout(timer); // 🔥 取消定时器
alert('定时器已取消!');
};
setInterval:循环定时器
每隔指定时间就执行一次,无限循环,直到你手动停止。
html
<!--显示点击时间-->
<div id="clock"></div>
<script>
setInterval(() => {
// 这里写要重复执行的代码
}, 间隔时间(毫秒));
const clock = document.getElementById('clock');
// 每隔1秒更新一次时间
setInterval(() => {
const now = new Date();
const time = now.toLocaleTimeString(); // 获取当前时间字符串
clock.innerText = time;
}, 1000);
</script>
怎么清除它? clearInterval
html
<div>倒计时:<span id="count">10</span>秒</div>
<button id="stopBtn">停止倒计时</button>
<script>
let count = 10;
const countSpan = document.getElementById('count');
// 把定时器存到变量里
const timer = setInterval(() => {
count--;
countSpan.innerText = count;
// 倒计时到0时,自动停止
if (count === 0) {
clearInterval(timer); // 🔥 清除定时器
alert('倒计时结束!');
}
}, 1000);
// 点击按钮手动停止
document.getElementById('stopBtn').onclick = function() {
clearInterval(timer);
alert('倒计时已停止!');
};
</script>
如果不清除,它会一直运行,即使你关闭了弹窗、切换了页面,它还在后台跑,会导致内存泄漏(页面越来越卡)。
定时器异步
首先澄清一个误区:JS 里没有 "真正的多线程异步" ,所有异步都是基于单线程事件循环的。
但定时器(setTimeout/setInterval)和 async/await(背后是 Promise)确实有本质区别的。
核心前提:JS 的任务队列分两种
JS 事件循环里,异步代码会被分到两个不同的队列:
- 宏任务(Macro Task) :定时器、DOM 事件、
script整体代码等 - 微任务(Micro Task) :
Promise.then/catch/finally、async/await(底层是 Promise)
优先级规则: 每次事件循环,先清空所有微任务,再执行一个宏任务。
同步代码 >
async/await(微任务)> 定时器(宏任务)
经典面试题: 打印顺序
js
console.log('1. 同步代码'); // 同步,最先执行
// 宏任务:定时器
setTimeout(() => {
console.log('4. 宏任务(定时器)');
}, 0); // 延迟 0 毫秒
// 微任务:Promise
Promise.resolve().then(() => {
console.log('3. 微任务(Promise)');
});
// async/await 也是微任务
async function test() {
await Promise.resolve();
console.log('3. 微任务(async/await)');
}
test();
console.log('2. 同步代码'); // 同步,继续执行
输出顺序:
- 同步代码
- 同步代码
- 微任务(Promise)
- 微任务(async/await)
- 宏任务(定时器)