引言

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 属性

1. 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新增的,使用时需注意兼容性问题。

此处盗了个图:

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

3、总述

除defer外,浏览器在下载完 JS 的内容后就会立即对其解析和执行,不管是同步加载还是异步加载。

文章中提到的异步加载,只能做到下载时的异步,但执行的时候依然会阻塞浏览器任何操作。
 
利用特殊的技巧可以做到 下载 与 执行的分离,下次再写了,天色太晚困的慌~。

JS的同步和异步加载的更多相关文章

  1. Angular.JS + Require.JS + angular-async-loader 来实现异步加载 angular 模块

    传统的 angular 应用不支持异步加载模块,必须在 module 启动的时候,所有模块必须预加载进来. 通过使用 angular-async-loader 库,我们可以使用 requirejs 等 ...

  2. JS文件延迟和异步加载:defer和async属性

    -般情况下,在文档的 <head> 标签中包含 JavaScript 脚本,或者导入的 JavaScript 文件.这意味着必须等到全部 JavaScript 代码都被加载.解析和执行完以 ...

  3. H5+JS+JQuery+ECharts实现异步加载

    这几天,看了一下ECharts官网的API和Demo发现很有意思,于是就利用模型预测产生的数据做一个伪实时的动态数据显示 . 首先,创建一个index.html的文件,我用的vscode打开的,进行编 ...

  4. Vue.js 子组件的异步加载及其生命周期控制

    前端开发社区的繁荣,造就了很多优秀的基于 MVVM 设计模式的框架,而组件化开发思想也越来越深入人心.这其中不得不提到 Vue.js 这个专注于 VM 层的框架. 本文主要对 Vue.js 组件化开发 ...

  5. jquery.datatable.js与CI整合 异步加载(大数据量处理)

    http://blog.csdn.net/kingsix7/article/details/38928685 1.CI 控制器添加方法 $this->show_fields_array=arra ...

  6. [转载]Javascript 同步异步加载详解

    http://handyxuefeng.blog.163.com/blog/static/4545217220131125022640/ 本文总结一下浏览器在 javascript 的加载方式. 关键 ...

  7. 关于requireJS的同步加载和异步加载

    这篇随笔主要记录require('name')和require(['name1','name2'])在同步和异步加载使用的区别 1.require('name')同步加载模块的形式 define(fu ...

  8. Javascript 异步加载详解(转)

    本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属 ...

  9. Javascript 异步加载详解

    Javascript 异步加载详解 本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy ...

随机推荐

  1. 阿里云宣布进入 Serverless 容器时代,推出弹性容器实例服务 ECI

    摘要: 阿里云宣布弹性容器实例 ECI(Elastic Container Instance)正式商业化. 为了应对业务高峰,打算提前多久执行ECS扩展?买了ECS虚拟机,容器规格不能完美装箱怎么办? ...

  2. hadoop快照管理

    快照相当于对目录做备份,并不会复制所有文件,而是记录文件的变化命令用法 ()hdfs dfsadmin -allowSnapshot 路径 (开启指定目录的快照功能) ()hdfs dfsadmin ...

  3. HDU - 1560 DNA sequence

    给你最多8个长度不超过5的DNA系列,求一个包含所有系列的最短系列. 迭代加深的经典题.(虽然自己第一次写) 定一个长度搜下去,搜不出答案就加深大搜的限制,然后中间加一些玄学的减枝 //Twenty ...

  4. fiddler设置抓取HTTPS协议数据包

    1.打开工具里的选项 2.选择弹窗中的HTTPS选项,如下图进行勾选 3.若浏览器显示不安全链接则需要添加证书 提示如下点击确定证书安装成功,可以查看安装的证书,点击Action 下图即可查看fidd ...

  5. day 64 Django基础十之Form和ModelForm组件

    Django基础十之Form和ModelForm组件   本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Mod ...

  6. c++ const的用法

    1.修饰成员变量 int value=0; int *p=&value; const int *p_c=&value;//指针指向常量,但是指针所指向的地址可以修改(int const ...

  7. js比较常用的

    1. <a href="javascript:void(0);" id="div1_bu" >点击链接可以删除div2</a> 超链接的 ...

  8. 非常棒的java在线编译平台

    1.godingground https://www.tutorialspoint.com/compile_java_online.php 2.ideone.com 3.jdoodle在线Java编译 ...

  9. 16.ajax_case06

    # 抓取华尔街见闻实时快讯 # https://wallstreetcn.com/live/global?from=navbar import requests import json header ...

  10. 【转载】flex布局超过显示省略号

    <div class="main"> <div class="content"> <h4 class="name&quo ...