1 定义与用法

1.1 setTimeout

1.1.1 定义

在指定的毫秒数后调用函数或计算表达式

1.1.2 用法

setTimeout(code/function, milliseconds, param1, param2, ...)

1.1.3 技术细节

  • code/function :必需,要调用一个代码串,也可以是一个函数
  • milliseconds :可选,执行或调用 code/function 需要等待的时间,以毫秒计。默认为 0 ,最短为4ms
  • param1, param2 :可选,传给执行函数的其他参数
  • 返回值 :返回一个 ID(数字),可以将这个ID传递给 clearTimeout() 来取消执行
    const fun = (param1, param2) => {
    console.log(param1, param2);
    }
    setTimeout(fun)
    setTimeout(fun, 1000, 'param1', 'param2')

1.2 setInterval

1.2.1 定义

按照指定的周期(以毫秒计)来调用函数或计算表达式

1.2.2 用法

setInterval(code/function, milliseconds, param1, param2, ...)

1.2.3 技术细节

  • code/function :必需,要调用一个代码串,也可以是一个函数
  • milliseconds :必需,周期性调用 code/function 之间的时间间隔,以毫秒计,最短为10ms
  • param1, param2 :可选,传给执行函数的其他参数
  • 返回值 :返回一个 ID(数字),可以将这个ID传递给 clearInterval() 来取消执行
    const fun = (param1, param2) => {
    console.log(param1, param2);
    }
    // setInterval(fun) //milliseconds 参数必须,否则疯狂执行代码块
    setInterval(fun, 1000, 'param1', 'param2')

2 setInterval缺陷

2.1 无视代码错误

即使调用的代码报错了, setInterval 还是会周期性调用代码块

let count = 1
setInterval(() => {
count++
console.log(count);
if(count > 3) throw new Error('setInterval 报错')
}, 1000)

改用 setTimeout

let count = 0
const fun = () =>{
setTimeout(() => {
count++
console.log(count);
if(count > 3) throw new Error('setTimeout 报错')
fun()
}, 1000);
}
fun()

2.2 无视网络延迟

在使用 Ajax 轮询服务器是否有新数据时,如果网络状态不佳,一个接口下发后还没有返回结果,此时 setInterval 还是会周期性调用代码块,导致客户端网络队列塞满 Ajax 请求

const http = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, 3000);
})
}
setInterval(async () => {
await http()
console.log('setInterval');
}, 1000)

改用 setTimeout

const http = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, 3000);
})
}
const fun = () =>{
setTimeout(async () => {
await http();
console.log('setTimeout');
fun()
}, 1000);
}
fun()

2.3 不保证间隔执行

setInterval 周期性添加执行器到任务队列,如果调用的代码执行的时间大于设置时间间隔,它会跳过调用,这就导致漏执行

3 优雅轮询

递归调用 setTimeout() ,不需要后调用 clearTimeout() 清除定时器

let timer = null
const interval = () => {
timer = setTimeout(() => {
// 执行代码块
interval()
}, 1000)
}
interval()
// 清除
setTimeout(() => {
clearTimeout(timer)
}, 5000);