同步加载
这是大家熟知的js加载方式,这种方式是同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。
<script src="http://yourdomain.com/script.js"></script>
异步加载
既然有同步那必然就会有异步,js加载的异步是什么样的呢,看代码 以上两种都是异步,特别之处就是加了defer和async属性。 defer和async的区别在于:
async 脚本在script文件下载完成后会立即执行,并且其执行时间一定在 window的load事件触发之前。这意味着多个async脚本很可能不会按其在页面中的出现次序顺序执行。
defer执行时机为DOM解析完成后,document的DOMContentLoaded事件触发之前。浏览器确保多个 defer 脚本按其在HTML页面中的出现顺序依次执行。
值得注意的是
在异步加载的时候,无法使用 document.write 输出文档内容。 在同步模式下,document.write 是在当前 script所在的位置输 出文档的。
而在异步模式下,浏览器继续处理后续页面内容,根本无法确定 document.write 应该输出到什么位置,所以异步模式下 document.write 不可行。
而到了页面已经 onload 之后,再执行 document.write 将导致当前页面的内容被清空,因为它会自动触发 document.open 方法。
封装一个函数兼容性的异步加载js文件并且可以按需执行该文件里面的函数(按需加载)
方法一
<script>
function loadScript(url,callback){
//url是按需加载的js文件
//callback是按需加载的js文件中某个函数
// 1. 创建一个script标签
var script = document.createElement('script');
// 处理ie的兼容
if(script.readyState){
script.onreadystatechange = function(){
// 如果script已经下载完成
if(script.readyState == 'complete' || script.readyState == 'loaded'){
callback();
}
}
}else{
// 监听script的下载的状态 当状态变为下载完成后 再执行callback
script.onload = function(){
callback();
}
}
//在后面引入的目的是如果在IE上如果下载太快(比读程序还快)
//IE的readystatechange 事件检测状态码的时候,它早已经从loading变成complete或者loaded(以极快的速度加载完了文件,你还没来得及检测)
// 那你再检测它就不会变了,它一直都是complete或者loaded
//这个时候就是马后炮了,检测也没用了。
// 2. 给script标签添加src 引入一个js文件
script.src = url;
// 3. 追加到body
document.body.appendChild(script);
}
</script>
方法二
let loadUrls=[]
function loadJs(src) {
return new Promise((resolve, reject) => {
if (loadUrls.indexOf(src)>-1) {//如果注册过该JS了 直接返回
resolve()
return
}
let script = document.createElement('script');
script.type = "text/javascript";
script.src = src;
document.body.appendChild(script);
script.onload = () => {
loadUrls.push(src)//注册成功添加到已注册列表
resolve();
}
script.onerror = () => {
reject();
}
})
}
export default loadJs