java解决js异步加载_JS异步加载的三种方案

js加载的缺点:加载工具方法没必要阻塞文档,个别js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。

有些工具方法需要按需加载,用到再加载,不用不加载。

一、defer与async

1.defer是IE独有的一种js异步加载模式,通过src加载的JS会等到文档解析完才会执行(document.readyState="interactive")。在script标签内部也可以写入内部JS代码,但是直接写入的内部JS代码会同步执行。

//写这里的代码是同步执行

2.asyn是W3C的标准异步加载模式,通过src加载的JS要等所有资源加载完以后执行(例如:img)(docuement.readyState="complete"),通过asyn异步加载的外部JS才会执行,但是asyn模式的script标签内不能写JS代码。

//这里不能写代码

因为asyn是W3C标准,IE9之前都不兼容,所以还是很鸡肋。

二、通过插入script标签的方式实现兼容模式的JS异步加载

通过插入script标签的方式实现JS异步加载的原理其实很简单,直接来代码:

functionloadScript(url){varscript=document.createElement("script");//新建一个script标签

script.type="text/javascript";//添加type属性

//绑定src,实现异步加载

script.src=url;//document.head.appendChild(script);切勿这么做,IE7和IE5上document没有head的DOM对象属性。

varhead=document.getElementsByTagName("head")[0];//插入script标签

head.appendChild(script);//把script添加到domTree节点中,并且会触发执行

}

loadScript("xxx.js");

异步加载的JS会什么时候执行呢?执行会不会阻塞HTML解析呢?基于异步加载方法来一波测试:

//这里是异步加载的代码

-----------------------------------------------------------------------------

//这里是异步加载的外部JS文档内容

var n =Number(new Date());

var n2 = Number(new Date());

while((n2 - n)

n2= Number(newDate());

console.log(1);

}

测试执行的结果:

---- 打印39733次1

---- 告诉我什么时候执行的

上面的测试结果告诉了我们,通过插入script异步加载的JS,加载完以后就会立即执行。并且执行的时候会阻塞HTML解析。

先来说说我为什么要在中间加入一行外部CSS代码,我们知道CSS是异步加载,但是CSS的加载会阻塞内部JS的执行,所以足够我测试的外部JS加载了。也就是说在内部JS执行前,外部JS肯定加载完成了,如果外部JS不会阻塞HTML解析也就不会在内部JS之前执行,但是测试的结果是通过添加script标签异步加载的外部JS在内部JS之前执行了,所以就说明了这种异步加载JS的方式加载完以后就会立即执行,并且如果HTML没有解析完就会阻塞HTML解析。

那为什么还需要这样的外部加载方式呢?

我们知道同步加载JS会阻塞HTML解析,而网络因素又是非常不可控的因素,如果某个同步加载的外部JS出现网络不畅通,就会一直阻塞页面。如果是一些工具脚本,不需要修改DOM的话,或者是一些不是一定需要的脚本(比如某个特定事件的JS脚本就可以用这种方式来加载),甚至可以在页面渲染完以后通过某个事件触发来加载它。

既然是异步加载的JS脚本,我们就有必要知道它什么时候加载完了,好方便我们使用,所以下面再来丰富以下这个异步加载JS的方法:

function loadScript(url,callback){

var script = document.createElement("script");//新建一个script标签

script.type="text/javascript";//添加type属性

if(script.readyState){

script.onreadystatechange = function(){

//script.readyState发生改变时触发script.onreadystatechange

if(script.readyState == "complete" || script.readyState == "loaded"){

//script.readyState -->状态码初始值是“loading”,根据文件加载进度,值发生改变

//IE通过script.readyState的状态码监听异步文件加载进度

tools[callback]();//采用对象属性调用需要执行的方法 -- 这里按需要使用

//看到有前辈说IE7和IE5有时候可能会即有"complete",又有"loaded"状态,为了防止万一可以在这里清除监听事件

script.onreadystatechange = null;

}

}

}else{

script.onload = function(){//script.onload-->表示加载完成以后执行

//除IE以外 Safari chrome firefox opera都兼容

tools[callback]();

}

}

//异步加载文件,必须放在事件添加后面,要不然出现先加载完了,事件函数没有绑定的的情况就不会触发了

script.src = url;

//document.head.appendChild(script);切勿这么做,IE7和IE5上document没有head的DOM对象属性。

var head = document.getElementsByTagName("head")[0];

head.appendChild(script);//把script添加到domTree节点中,并且会触发执行

}

W3C标准中有onload事件可以监听外部脚本是否加载完成,所以IE就需要兼容。

IE的script元素的DOM对象上有readyState属性记录外部资源的加载状况,与document对象上的readyState属性一样,有四个值:

uninitialized -- 还未开始载入;

loading - 载入中;

interactive - 已加载,文档与用户可以开始交互;

complete - 载入完成;(有些版本是loanded,听说有些版本这两个状态都会出现本人没遇到过)

(tools[callback](),是我测试回调外部脚本的方法,这个不重要,主要看需求,反正这里就是说明外部JS已经加载完毕了,可以处理自己要处理的程序了)

凌晨了,晚安。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值