js的异步加载你真的懂吗
面试高频之js的异步加载
讲这个问题之前, 我们从另一个面试高频问题来切入,
我们的web页面从开始解析到页面渲染完成都经历了什么 ?
1 , 创建document对象, 开始解析页面, 此时document.readyState = 'loading'
2 , 遇到link标签引入的css文件, 创建线程并异步加载css,继续解析文档
3, 遇到script标签引入的外部脚本 , 如果script标签的属性设置了defer或者async 则 创建线程异步加载js , 否则同步加载js(阻塞了dom的解析) , 继续解析文档 (async脚本加载完就执行)
4 , 遇到img等要加载资源的标签, 正常解析dom 标签 , 异步加载src , 继续解析文档
5 , 文档解析完毕 , document.readyState = 'interactive' , 所有defer脚本按顺序执行,并且document会触发 DOMContentLoaded事件 , 标志着程序从同步脚本执行阶段转化成事件驱动阶段
6 , 当所有async 脚本 加载并执行 完毕 , img 加载完毕 , document.readyState = 'complete' , window 触发 load 事件 。
7 从此 以异步响应的方式处理用户输入, 网络事件等 。。。。。。
ok , 光说没用, 我们来看看真相是否只有一个。。。
document.onreadystatechange = () => {
console.log(document.readyState)
};
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded')
});
window.onload = () => {
console.log('load')
};
注意一点, DOMContentLoaded 事件 只能用 addEventListener 来绑定
结果是这样:

按顺序打印出来了 。。。
上文我们提到只有设置了defer /async 的 script 脚本 才能异步加载 ,
注意defer 有些低版本浏览器不兼容,
async是W3C的标准,但只能在引入外部js文件时使用,
当然,我们最常用的是把script标签放在body 后面 ,这样就不会阻塞dom解析
还有一种情况, 动态添加的script脚本也是异步加载的, 基于此 我们来封装一个 异步加载script脚本的函数
function loadScript (url, callback) { // 传入url , 和要执行的回调函数
const script = document.createElement('script');
script.type = 'text/javascript'; // 创建一个script标签
if (script.readyState) { // 做兼容
script.onreadystatechange = () => { // readyState变化触发
if (script.readyState === 'complete' || script.readyState === 'loaded') { // 兼容
callback(); // 加载完执行回调
}
}
} else {
script.onload = () => {
callback(); // 加载完执行回调
}
}
script.src = url;
document.head.appendChild(script); // 插入head中
}
以上就是 js 异步加载 的 全部内容了, 欢迎小伙伴们补充
js的异步加载你真的懂吗的更多相关文章
- Vue中结合Flask与Node.JS的异步加载功能实现文章的分页效果
你好!欢迎阅读我的博文,你可以跳转到我的个人博客网站,会有更好的排版效果和功能. 此外,本篇博文为本人Pushy原创,如需转载请注明出处:http://blog.pushy.site/posts/15 ...
- js滚动异步加载数据的思路
<body> <div style="width:200px; height:1000px; border:1px solid red;" id="to ...
- JS异步加载的三种方案
js加载的缺点:加载工具方法没必要阻塞文档,个别js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作. 有些工具方法需要按需加载,用到再加载,不用不加载. 一.def ...
- 异步加载的JS如何在chrome浏览器断点调试?
我们常常利用chrome强大的控制台Sources下面进行代码断点调试,但是通过$.getScript等异步加载JS的方式在Sources里面就是找不到,那如何进行debug断点调试呢? 方案一: 在 ...
- 不得不说的JavaScript异步加载
同步加载的问题 默认的js是同步加载的,这里的“加载”可以理解成是解析.执行,而不是“下载”,在最新版本的浏览器中,浏览器对于代码请求的资源都是瀑布式的加载,而不是阻塞式的,但是js的执行总是阻塞的. ...
- javascript 同步加载与异步加载
HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值. defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面 ...
- Highcharts 异步加载数据曲线图表
导入 data.js 文件 异步加载数据需要引入以下js 文件: <script src="http://code.highcharts.com/modules/data.js&quo ...
- Javascript 文件的同步加载与异步加载
HTML 4.01 的script属性 charset: 可选.指定src引入代码的字符集,大多数浏览器忽略该值.defer: boolean, 可选.延迟脚本执行,相当于将script标签放入页面b ...
- Highcharts 基本曲线图;Highcharts 带有数据标签曲线图表;Highcharts 异步加载数据曲线图表
Highcharts 基本曲线图 实例 文件名:highcharts_line_basic.htm <html> <head> <meta charset="U ...
随机推荐
- SQL Server复制表结构和表数据生成新表的语句
参考:http://topic.csdn.net/t/20020621/09/820025.html SELECT * INTO newTableName FROM oldTabl ...
- 【js-xlsx和file-saver插件】前端html的table导出数据到excel的表格合并显示boder
最近在做项目,需要从页面的表格中导出excel,一般导出excel有两种方法:一.习惯上是建模版从后台服务程序中导出:二.根据页面table中导出:综合考虑其中利弊选择二.根据页面table中导出ex ...
- 使用Navicat连接阿里云服务器上的MySQL数据库--转
手把手教你如何正确连接阿里云服务器上的数据库: 1.首先打开Navicat,文件>新建连接>MySQL连接,其他的如一图所示. 2.因为是连接服务器上的MySQL,所以我们使用SSH连接, ...
- 关于react router 4 的小实践
详细代码栗子:https://github.com/wayaha/react-dom-CY clone然后 npm install npm start 分割线 1.这个项目使用create-react ...
- 修改input获取焦点背景黄色
input:-webkit-autofill { -webkit-box-shadow: 0 0 0px 1000px white inset !important; }
- java 用ant打包成jar文件
一.下载ant包,解压放放到你的项目中 二.在ant文件夹下创建一个build.xml文件,内容如下 <?xml version="1.0" encoding="G ...
- Setting up Latex-vim (or Latex-suite) plugin within macVim under Mac OSX Yosemite 2015-1-20 by congliu
1. Overview: Vim是命令行下的文本编辑程序,gVim是Vim的Linux下的图形化版本,macVim是Mac下的图形化版本 Latex-vim是vim写Latex文件时的插件 Skim是 ...
- scrapy中 Mongo的存储
import pymongo MONGO_HOST = 'localhost' MONGO_PORT = 27017 MONGO_DB = 'today' MONGO_COLL = 'mm' clas ...
- java获取一个月的天数
import java.text.SimpleDateFormat; import java.util.Calendar; public class Test { public static void ...
- c# 将一个窗体显示在主窗体中
Form2 form = new Form2(); //实例化要添加的窗体 form.Show();//显示 form.TopLevel = false; //要将这个顶级窗口设置false pane ...