定时器详解和应用、js加载阻塞、css加载阻塞

1.setTimeout()、setInterval()详解和应用

1.1 详解: setTimeout、setInterval执行时机
1.2 存在问题: setInterval重复定时器可能存在的问题、解决方案
1.3 应用: Yeilding Processes(进程暂停)

​ 运行在浏览器中的JavaScript都被分配了一个确定数量的资源,不同于桌面应用往往能够随意控制他们要的内存大小和处理时间,Javascript被严格限制了,以防止恶意的Web程序员吧用的计算机搞挂了,其中一个限制是长时间运行脚本的制约,如果代码运行超过特定时长或者特定数量的语句就不让它继续执行,询问是允许其继续执行还是停止它。所有JavaScript开发人员的目标就是,确保用户永远不会再浏览器中看到这个令人费解的对话框。定时器是绕开此限制的方法之一

脚本运行时间长的2个原因

​ 1.过长的、过深嵌套的函数调用;

​ 2.进行大量处理的循环;

​ 这2种后者较为容易的被解决

进行大量处理的循环

​ 使用这种方式必须满足的要求:

​ 1.该处理不是必须同步完成

​ 2.数据不是必须按顺序完成

解决方案:数组分块

function chunk(arr, process, context){
    setTimeout(function () {
        var item = arr.shift()
        process.call(context, item)
        if(arr.length > 0){
         	setTimeout(arguments.callee, 100)  
         }
    }, 100)
}

使用场景建议:

​ 一旦某个函数的执行需要花50ms以上的时间完成,那么最好看看能否将任务分割为一系列可以使用定时器的小任务。

1.4 应用:函数节流

1.4.1 节流函数的起源

​ 浏览器中的某些计算和处理要比其他的开销大很多。例如,DOM比起非DOM交互需要更多的内存和CUP时间。连续尝试进行过多的DOM相关操作可能会导致浏览器挂起,有时候甚至奔溃。尤其在IE中使用onresize时处理程序的时候很容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize事件处理程序内部如果尝试进行DOM操作,其高频率的更改可能会让浏览器奔溃。为了绕开这个问题,可以使用定时器对该函数进行节流。

​ **1.4.2 节流函数的原理 **

​ 某段代码不能在没有间隔的情况下连续重复执行。

​ 第一次调用函数,创建一个定时器,在指定的时间间隔后执行代码,当第二次调用该函数时,他会清除前一次的定时器并设置另一个定时器。如果前一个定时器已经执行了,这个操作没有任何意义。然后,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的只有一个:只有在执行函数的请求停止了一段时间之后才执行。

1.4.3 适合节流的场景:周期性执行的代码

​ **1.4.4 节流函数的实现 **

var processor = {
    timeoutId: null,
    performProcessing: function () {
        //实际执行的代码
    },
    process: function () {
        clearTimeout(this.timeoutId)
        
        var that = this
        this.timeoutId = setTimeout(function () {
            that.performProcessing()
        }, 100)
    }
}

​ **1.4.5 节流函数实现的简化 **

function throttle (cb, context) {
    clearTimeout(cb.ID)
    
    cb.ID = setTimeout(function () {
        cb.call(context)
    }, 1000)
}

2.CSS加载是否影响DOM的解析和渲染

​ 给浏览器设置节流和延迟:使出现的效果能够在自己被自己察觉。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    h1 {
      color: red!important;
    }
  </style>
  <script>
    function h () {
      let h1 = document.getElementById('h1')
      console.log( h1 )
    }
    setTimeout(h, 0)
  </script>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>

  <h1 id="h1">这是红色</h1>

</body>
</html>

结果:在css正在下载时,h1标签被控制太打印出来,但是页面没有文字。

结论:css加载会阻塞DOM树渲染,不会阻塞DOM树的解析。

个人看法:这样子做还是符合优化的正常逻辑的,css不会阻塞解析;如果不阻塞css渲染,等这个css加载完成后,会触发回流和重绘额外增加性能开销,所以还不如直接等css加载完成后再来渲染。

3.css加载是否影响js加载?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    h1 {
      color: red!important;
    }
  </style>

  <script>
    console.log('before css')
    var startDate = new Date()
  </script>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>

  <h1 id="h1">这是红色</h1>

  <script>
    var endData = new Date()
    console.log('after css')
    console.log('已经过了' + (endData - startDate))
  </script>
</body>
</html>

结果:在css正在加载时,控制台内容:before css

​ css加载完成时,控制台内容:

before css
after css
已经过了3444

结论:css加载时,会阻塞js的执行。

4.js加载是否影响DOM的解析和渲染、js执行、css加载?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js"></script>
  <script>
    console.log(1111)
  </script>
  <style>
    h1 {
      color: red!important;
    }
  </style>
</head>
<body>

  <h1 id="h1">这是红色</h1>

</body>
</html>

现象:Loading js时,后续js没有执行,后续DOM没有解析。

结论:js加载阻塞

posted @ 2019-04-18 17:55  DaivdAndLemon  阅读(684)  评论(0编辑  收藏  举报