async、defer、动态加载js
Js 中的async属性和defer属性
一、async和defer
async:指外部js文件和当前html页面同时加载(异步加载),在当前js文件加载完成后,执行js代码
defer:指外部js文件和当前html页面同时加载(异步加载),但只在当前页面解析完成之后执行js代码
二、async和defer属性只对外部脚本文件有效:
上图表明:这两个属性在内嵌式js中无效
三、当使用async和defer属性时, js 代码中的document.write(…);无法生效。
因为当当前页面加载和解析完成之后,文档流已经关闭,所以无法向页面中写入内容了(可以使用DOM方法写入内容)
对“文档”执行“写入”失败:除非显式打开文档,否则无法从异步加载的外部脚本写入文档。
四、外部 js 文件的异步加载和执行
拥有async属性和defer属性的外部js文件属于异步加载,普通外部js文件属于同步加载。
异步加载:指同时加载,即某个js文件加载的同时,其余文件也可以加载
同步加载:指某个js文件加载的同时,其余文件不能加载,
async和defer的区别在于:async在当前页面加载的同时就可以执行js代码(或者说在当前js加载完成后执行)。defer在当前页面加载并解析完成之后才执行js代码。
如async:
如defer:
五、总结
①async和defer都属于异步加载
②async是当前js文件加载完成后执行js,defer是延迟执行(推迟解释,当前html页面解析完成后执行)js
js 怎么动态加载js文件
- 【基本优化】
将所有需要的之前,确保脚本执行之前完成页面渲染,而不会造成页面堵塞问题,这个大家都懂的。
- 【合并 JS 代码,尽可能少的使用script标签】
最常见的方式就是带代码写入一个js文件中,让页面只使用一次标签来引入
- 【无堵塞加载 JS 】
通过给script标签增加 defer属性或者是 async 属性来实现
注解:
async和defer不同之处是:async加载完成后会自动执行脚本,defer加载完成后需要等待页面也加载完成才会执行代码
-
【动态创建script来加载-推荐】
function loadJS (url, callback) {
var script = document.createElement('script');
var fn = callback || function () {};
script.type = 'text/javascript';
// IE
if (script.readyState) {
script.onreadystatechange = function () {
if( script.readyState == 'loaded' || script.readyState == 'complete' ){
script.onreadystatechange = null;
fn();
}
};
} else {
//其他浏览器
script.onload = function () {
fn();
};
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
// 用法
loadJS('file.js', function () {
alert('加载成功');
});
- 谷歌浏览器运行效果,script被动态创建在head中
- 建议大家可以封装成类库,单独引入。
该原理实现的也有很多不错的js类库可以使用,如LazyLoad.js支持数组的形式引入,打开浏览器在network中可看到js是同步加载的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="text/javascript" src="js/lazyload.js"></script>
<script type="text/javascript">
(function () {
LazyLoad.js(['js/jquery-1.11.min.js', 'js/jquery.flexslider-min.js', 'js/app.js'], function () {
App.init();
});
})();
</script>
</body>
</html>
-
【XHR加载】
// 使用ajax方式加载,代码如下:
var xhr = new XMLHttpRequest;
xhr.open('get', 'file.js', true);
xhr.onreadystatechange = function () {
if ( xhr.readyState == 4 ) {
if( xhr.status >=200 && xhr.status < 300 || xhr.status == 304 ){
var script = document.createElement('script');
script.type = 'text/javascript';
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);
- 总结
最好的方式还是使用动态创建script的方式加载,当动态创建script,浏览器会分配一个线程去下载src指向的资源,多个script也是同步下载的
转载自:https://juejin.cn/post/7236383034559905849