setTimeout 与 setInterval —— 实现优雅轮询

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);

猜你喜欢

转载自blog.csdn.net/weixin_36757282/article/details/127575238