关于setTimeout的小“秘密”

Published on with 0 views and 0 comments

如果JS某段代码执行时间过久,会影响定时器任务的执行

function bar() {
    console.log('bar') // bar并不会被立即打印,而是等到for循环结束之后才被打印
}
function foo() {
    setTimeout(bar, 0);
    for (let i = 0; i < 5000; i++) {
        console.log(i)
    }
}
foo()

如果setTimeout存在嵌套,那么系统会设置最短时间间隔为4毫秒

在Chrome中嵌套调用大于等于5次,系统会判断该函数方法被阻塞了,如果定时器的调用时间间隔小于 4 毫秒,那么浏览器会将每次调用的时间间隔设置为 4 毫秒

function testSetTimeoutFor4MS () {
  let index = 0
  let timer = null

  function cb () { 
    console.timeEnd(index)
    if (index >= 10) {
      clearTimeout(timer)
      timer = null
      return false
    }
    console.time(++index)
    timer = setTimeout(cb, 0)
  }

  console.time(index)
  timer = setTimeout(cb, 0)
}

image.png

未激活的页面,setTimeout执行最小间隔是1000毫秒

如果标签不是当前的激活标签,那么定时器最小的时间间隔是 1000 毫秒,目的是为了优化后台页面的加载损耗以及降低耗电量

function testSetTimeoutWhenVisibilityChange () {
  document.addEventListener("visibilitychange", () => {
    console.log(document.visibilityState)
  })

  let index = 0
  let timer = null

  function cb () { 
    console.timeEnd(index)
    if (index >= 1000) {
      clearTimeout(timer)
      timer = null
      return false
    }
    console.time(++index)
    timer = setTimeout(cb, 0)
  }

  console.time(index)
  timer = setTimeout(cb, 0)
}

image.png

延时执行有最大值

Chrome、Safari、Firefox 都是以 32 个 bit 来存储延时值的,32bit 最大只能存放的数字是 2147483647 毫秒,这就意味着,如果 setTimeout 设置的延迟值大于 2147483647 毫秒(大约 24.8 天)时就会溢出,那么相当于延时值被设置为 0 了,这导致定时器会被立即执行

function hello(){
  console.log("hello")
}
var timerID = setTimeout(hello, 2147483648);//会被理解调用执行

标题:关于setTimeout的小“秘密”
作者:lj0812
地址:https://blog.hereis.me/articles/2020/04/28/1588069259467.html