JS 默认是单线程:代码一行一行排队执行,同一时间只能干一件事。 如果一段代码执行很久,后面代码就会卡住(阻塞)。
异步 + 定时器解决的问题:不让长时间 / 等待类的任务卡住后面代码,先把等待任务放到一边,继续往下跑主线代码;等时间到了,再回头执行这个任务。
一句话:不用原地死等,程序可以继续做别的事,时间到了再执行指定代码。
⚠️ 定时器不是 “到点立刻执行”,是到点把回调放进任务队列,等主线空闲才执行。
二、两个定时器:setTimeout和setInterval
1. setTimeout 延时定时器(一次性)
- 作用:延迟多少毫秒后,执行一次代码,只跑 1 次
- 单位:毫秒 ms,1s = 1000ms
- 语法(按你习惯:用 let + 箭头函数)
// 语法:let 变量 = setTimeout(回调函数, 等待毫秒数) let timer1 = setTimeout(()=>{ console.log("2秒之后打印这句话,只执行一次"); },2000) // 清除定时器,取消任务 clearTimeout(timer1)应用场景 setTimeout
- 弹窗延迟弹出(进入页面 2 秒后弹出欢迎提示)
- 搜索框防抖(用户停止输入一小会儿,再发请求,减少请求次数)
- 过渡动画延时、提示消息自动消失(toast 提示 3 秒消失)
- 模拟接口请求,写测试代码(模拟等待服务器返回数据)
2. setInterval 间隔定时器(循环重复执行)
- 作用:每隔固定毫秒,重复执行代码,不停循环
let timer2 = setInterval(()=>{ console.log("每隔1秒打印一次"); },1000) // 停止循环定时器 clearInterval(timer2)应用场景 setInterval
- 倒计时(验证码倒计时、活动秒杀倒计时)
- 轮播图自动切换
- 定时轮询接口(每隔几秒去后台拿最新数据,实时刷新页面)
- 数字跳动动画
三、异步基础(宏任务,定时器属于宏任务)
JS 异步分:宏任务、微任务setTimeout / setInterval属于宏任务执行顺序口诀:
主线同步代码 → 全部微任务 → 再取宏任务执行
举个例子帮理解:
console.log("同步代码 最先执行"); let t = setTimeout(()=>{ console.log("定时器,最后才执行"); },0) console.log("同步代码 第二行");输出顺序:
同步代码 最先执行 同步代码 第二行 定时器,最后才执行哪怕延时写 0,也不是立刻执行!只是尽快放进宏任务队列,等主线全部做完才执行。
四、常见坑(作业必考)
- 单位是毫秒,不是秒,别直接写
setTimeout(fn,2)当成 2 秒,这是 2 毫秒 - 定时器返回值是编号数字,保存这个编号,才能用 clear 清除;不清除会一直占用资源
- setInterval 容易累积误差:如果里面代码执行时间长,两次执行间隔会不准;精准倒计时推荐用
setTimeout递归代替 setInterval
// 递归版setTimeout,更精准的倒计时 let count = 10 let countDown = ()=>{ count-- console.log(count) if(count>0){ let timer = setTimeout(countDown,1000) } } countDown()- 定时器 this 指向问题:箭头函数不会改变 this,普通 function 会指向 window