setTimeout与setInterval

  • Chrome中使用延迟队列保存Chrome内部的延时任务和setTimeout提交的延时任务。当执行完消息队列中的任务之后就会开始执行延时队列的处理函数,然后延时队列处理函数会根据发起时间和延迟时间计算出到期任务。
  • setTimeout和setInterval不在JavaScript的规范中,由运行环境提供
  • 如果当前任务执行时间过久,会影响到定时器的执行
  • Chrome最小间隔1ms,存在嵌套会设置成4ms间隔时间
  • 如果当前页面标签没有被激活,那么setTimeout的执行最小时间间隔是1s,目的是优化加载消耗和耗电量
  • 时间间隔有最大值,当延时24.8天setTimeout就会溢出,致使延时函数被立即执行
  • setTimeout执行的函数this对象指向window,可以通过匿名函数或者bind方法解决
  • 对于每一个setInterval,队列中同时只能存在一个延时事件,后面的事件会被抛弃

requestAnimationFrame与requestIdleCallback

  • requestAnimationFrame: 告诉浏览器在下次重绘之前执行传入的回调函数(通常是操纵dom,更新动画的函数);由于是每帧执行一次,那结果就是每秒的执行次数与浏览器屏幕刷新次数一样,通常是每秒60次。

    • 如果想要实现动画效果,每一次执行回调函数,必须要再次调用 requestAnimationFrame 方法;与 setTimeout 实现动画效果的方式是一样的,只不过不需要设置时间间隔。

      1. let offsetTop = 0;
      2. const div = document.querySelector(".div");
      3. const run = () => {
      4. div.style.transform = `translate3d(0, ${offsetTop += 10}px, 0)`;
      5. window.requestAnimationFrame(run);
      6. };
      7. run();
    • 在 requestAnimationFrame 之前,主要借助 setTimeout/ setInterval 来编写 JS 动画,而动画的关键在于动画帧之间的时间间隔设置,这个时间间隔的设置有讲究,一方面要足够小,这样动画帧之间才有连贯性,动画效果才显得平滑流畅;另一方面要足够大,确保浏览器有足够的时间及时完成渲染。

  • requestIdleCallback: 会在浏览器空闲时间执行回调,也就是允许开发人员在主事件循环中执行低优先级任务,而不影响一些延迟关键事件。如果有多个回调,会按照先进先出原则执行,但是当传入了timeout,为了避免超时,有可能会打乱这个顺序。

代码

  1. //practice1
  2. setTimeout(()=>{console.log(5)},5)
  3. setTimeout(()=>{console.log(4)},4)
  4. setTimeout(()=>{console.log(3)},3)
  5. setTimeout(()=>{console.log(2)},2)
  6. setTimeout(()=>{console.log(1)},1)
  7. setTimeout(()=>{console.log(0)},0)
  8. //practice2
  9. console.log(1)
  10. setTimeout(() => {
  11. console.log(2)
  12. new Promise(resolve => {
  13. console.log(4)
  14. resolve()
  15. }).then(() => {
  16. console.log(5)
  17. })
  18. })
  19. new Promise(resolve => {
  20. console.log(7)
  21. resolve()
  22. }).then(() => {
  23. console.log(8)
  24. })
  25. setTimeout(() => {
  26. console.log(9)
  27. new Promise(resolve => {
  28. console.log(11)
  29. resolve()
  30. }).then(() => {
  31. console.log(12)
  32. })
  33. })