美文网首页javascript
JS的同步和异步加载

JS的同步和异步加载

作者: 张晖 | 来源:发表于2020-11-03 00:51 被阅读0次

引言

JS的“加载”不能理解为下载,它是分为两个部分:下载,执行。默认的JS加载是同步的,因为浏览器需要一个稳定的DOM结构,而执行JS时可能会对DOM造成改变,所以在执行JS时一定会阻塞HTML的渲染。我们可以使用一些方法使JS的下载不会阻塞HTML渲染,但不能使JS的执行阻塞渲染。

以下从几个方面解释JS的加载:

1、同步加载  
2、异步加载
  2.1、Script DOM Element
  2.2、onload 时的异步加载

1、同步加载

同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。使用方式如下:

<script src="http://domin1.com/script1.js"></script>
<script type="text/javascript">
  console.log('hello world');
</script>

这段代码中,如果请求的 script1.js 加载时间过长(domin1 被墙等原因),浏览器就会停止后续的文件下载,渲染,代码执行,第二个<script>中的"hello world"也无法显示。

以前的处理方法是把<script>放置于页面末尾的</body>之前,可以使页面先显示出来,但这也只是让页面渲染不被阻塞而已,对于上例第二个 <script> 的 JS 执行所造成的阻塞是无能为力的。

2、异步加载

异步加载又叫非阻塞,浏览器在下载 JS 同时,还会继续进行后续页面的处理,上例第二个<script>的JS执行便不会被阻塞。

2.1、Script DOM Element 法

此方法不要求JS同源,使用方式如下:

(function (){
    var async_script = document.createElement('script');
    async_script.type = "text/javascript";
    async_script.src = "http://domin.com/script.js";
    var x = document.getElementsByTagName("script")[0];
    x.ParentNode.insertBefore(async_script, x);
})();

以上代码使用 JS 创建了一个<script>插入到 document 中,便实现了异步加载 JS。
将JS代码包裹在匿名函数中并立即执行的方式是为了保护变量名不被泄露到外部可见。

但问题还是存在:这段代码在下载和执行完之前会阻止 onload 事件的触发,于是有了onload 时的异步加载。

2.2、onload 时的异步加载
(function() {
     function async_load(){
         var as = document.createElement("script");
         as.type = "text/javascript";
         as.src = "http://domain1.com/script.js";
         var x = document.getElementsByTagName("script")[0];
         x.parentNode.insertBefore(s, x);
     }
     if (window.attachEvent)
         window.attachEvent('onload', async_load);
     else
         window.addEventListener('load', async_load, false);
 })();

两段代码的区别在于这段不是马上异步加载 JS ,而是在 onload 开始时才异步加载,便不会阻塞 onload 事件触发。

2.3、async 和 defer 属性
//async属性:
<script src="script1.js" async="async"></script> 

//defer属性:
<script src="script2.js" defer="defer"></script> 

async 属性使加载和渲染后续文档元素的过程将和当前 js 的下载与执行并行进行(异步);
defer 属性使下载后续文档元素的过程将和 script.js 的下载并行进行(异步),但是 script.js 的执行要在所有元素(DOM)解析完成之后,DOMContentLoaded 事件触发之前完成。
但async属性是HTML5新增的,使用时需注意兼容性问题。

此处盗了个图:


image

该图中,绿线为HTML解析,蓝线为脚本下载,红线为脚本执行。
可以看出默认情况下也就是同步模式下,脚本的下载和执行会阻塞HTML解析;
异步模式中的asyncdefer两个属性在下载时均为异步不影响HTML解析,在执行时均阻塞HTML解析,但defer 胜在它可以控制脚本执行的时间,保证页面先加载出之后再执行脚本。

3、总述

defer外,浏览器在下载完 JS 的内容后就会立即对其解析和执行,不管是同步加载还是异步加载。
文章中提到的异步加载,只能做到下载时的异步,但执行的时候依然会阻塞浏览器任何操作。

相关文章

  • js加载同步还是异步? JSONP原理?

    1、浏览器端的js加载默认是同步还是异步?同步,可以人为设置异步;async让js异步加载,需要每个script标...

  • 系统源码简析

    同步加载 异步加载 页面的懒加载,只针对vue文件,js文件被放到app.js中了, 比如 share.js。 a...

  • JS的同步和异步加载

    引言 JS的“加载”不能理解为下载,它是分为两个部分:下载,执行。默认的JS加载是同步的,因为浏览器需要一个稳定的...

  • html,css,js加载顺序

    1. 加载方式 css 异步加载(不阻塞)js 同步加载(阻塞) 2. 放置顺序 css 放置于 标签中原因:...

  • 2021-07-14【unity】Addressble bund

    1.同步加载一个: 2.同步加载多个: 3.异步加载一个: 4.异步加载:

  • JS 函数的执行时机

    1.同步和异步的区别 我们都知道JS里面有同步和异步的区别,怎么理解同步和异步呢。一家餐厅吧来了5个客人,同步的意...

  • java_Ajax

    Ajax:(asynchronous js and xml) 异步的js和xml 指的是一种交互方式 异步加载,客...

  • 跳转场景

    同步加载 (同步加载:如果场景很大,有可能会卡顿。) 异步加载     需要三个场景来完成异步加载,开始场景、过渡...

  • webpack学习第十三步——懒加载和预请求

    同步引入 index.js 打开页面时就会引入lodash 异步引入可以懒加载 index.js 点击时才去请求异...

  • 关于JavaScript同步加载和异步加载

    关于同步加载和异步加载 同步加载:同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续...

网友评论

    本文标题:JS的同步和异步加载

    本文链接:https://www.haomeiwen.com/subject/htnvvktx.html