settimeout 模拟实现 setinterval

388 阅读1分钟

setInterval的缺点

“丢帧”现象:setInterval()仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中,即在向队列插入代码实例之前,会先检测是否正在执行该代码实例,以及队列中是否已经存在该代码实例,只要存在其一就都不会再向队列中插入。

实际代码执行间隔 <= 设定的时间间隔:比如一个1000ms的interval,在插入队列后因为前一个任务执行超时(假设超时800ms),导致该任务不能及时执行,当它执行完毕后(假设执行不耗时,即还剩下200ms),下一个代码(相隔200ms后)又立即添加到队列中,并立即执行,使得实际代码执行间隔(仅200ms)小于设定的间隔时间,极端条件下可能会出现代码实例连续执行的情况

通俗来说:每个 setTimeout 产生的任务会直接 push 到任务队列中;而 setInterval 在每次把任务 push 到任务队列前,都要进行一下判断(看上次的任务是否仍在队列中,如果有则不添加,没有则添加)。

function mySettimeout(fn,t){
  let timer=null
  function interval(){
    fn()
    timer=setTimeout(interval,t)
  }
  interval()
  return  {
    cancel:()=>{
      clearTimeout(timer)
    }
  }
}

const a=mySettimeout(()=>{
  console.log(1111)
},1000)

setTimeout(()=>{
  a.cancel()
},4000)
function mySettimeout(fn,t){
  const timer=setInterval(()=>{
    clearInterval(timer)
    fn()
  },t)
}
const b=mySettimeout(()=>{
  console.log(2222)
},3000)