同步加载与异步加载

这几天一直在忙项目上线的问题,碰到了好多问题,比如异步加载、事件冒泡、浏览器缓存。这篇文章主要是文件的同步加载和异步加载。

先说下我碰到的问题:项目要接入到支付宝城市服务中,但是安卓和ios设置支付宝的导航栏内容有差异。安卓和ios都是拿页面的title设置导航栏的内容,但是安卓支持用js动态的修改titleios是在页面初始化时会默认拿title作为导航栏内容,初始化后用JS动态修改无效。支付宝提供了设置支付宝导航的jsAPI,需要加载两个文件,我之前是在项目中直接加载这连个文件,在调用它提供的方法,没问题完美设置。但是后来我感觉这样不好我不是每个输出的商户都需要设置,所以我用navigator.userAgent判断是不是在支付宝客户端打开,在动态添加这两个JS文件,在这就出现问题了,你动态添加完JS后,马上执行里面的方法有时会出现错误,说明你还没有加载成功时就执行了方法。

这里就是我们经常说的同步加载与异步加载

1. 同步加载

我们平时最常使用的就是这种同步加载形式:

<script src="js/jQuery.js"></script> 

同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。

 js 之所以要同步执行,是因为 js 中可能有输出 document 内容、修改dom、重定向等行为,所以默认同步执行才是安全的。

以前的一般建议是把<script>放在页面末尾</body>之前,这样尽可能减少这种阻塞行为,而先让页面展示出来。

简单说:加载的网络 timeline 是瀑布模型,而异步加载的 timeline 是并发模型。

2. 常见异步加载(Script DOM Element

原生方法

(function() {
     var s = document.createElement('script');
     s.type = 'text/javascript';
     s.async = true;
     s.src = 'js/jQuery.js';
     var x = document.getElementsByTagName('script')[0];
     x.parentNode.insertBefore(s, x);
 })();

jQuery方法

$("head").append(jQuery.js)


异步加载又叫非阻塞,浏览器在下载执行 js 同时,还会继续进行后续页面的处理。

这种方法是在页面中<script>标签内,用 js 创建一个 script 元素并插入到 document 中。这样就做到了非阻塞的下载 js 代码。

3. onload 时的异步加载

(function() {
     function async_load(){
         var s = document.createElement('script');
         s.type = 'text/javascript';
         s.async = true;
         s.src = 'js/jQuery.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 事件触发的问题。

补充:DOMContentLoaded  OnLoad 事件

DOMContentLoaded : 页面(document)已经解析完成,页面中的dom元素已经可用。但是页面中引用的图片、subframe可能还没有加载完。

OnLoad:页面的所有资源都加载完毕(包括图片)。浏览器的载入进度在这时才停止。

4. jQuery的异步加载

jQuery.getScript(url, [callback])

参数:url:待载入 JS 文件地址。

callback:成功载入后回调函数。

$.getScript("test.js", function(){

alert("Script loaded and executed.");

});

这和前面的方法差不多加载 test.js 成功后,调用方法显示信息。

5async defer 属性

1. defer 属性

<script src="js/jQuery.js" defer></script> 

defer属性声明这个脚本中将不会有 document.write dom 修改。

浏览器将会并行下载 file.js 和其它有 defer 属性的script,而不会阻塞页面后续处理。

defer属性在IE 4.0中就实现了,超过13年了!Firefox 3.5 开始支持defer属性 

注:所有的defer 脚本保证是按顺序依次执行的。

2. async 属性

<script src="js/jQuery.js" async></script> 

async属性是HTML5新增的。作用和defer类似,但是它将在下载后尽快执行,不能保证脚本会按顺序执行。它们将在onload 事件之前完成。

Firefox 3.6Opera 10.5IE 9 和 最新的Chrome Safari 都支持 async 属性。可以同时使用 async defer,这样IE 4之后的所有 IE 都支持异步加载。

3. 详细解释

<script> 标签在 HTML 4.01 HTML5 的区别:

· type 属性在HTML 4中是必须的,在HTML5中是可选的。

· async 属性是HTML5中新增的。

· 个别属性(xml:space)在HTML5中不支持。

说明:

1. 没有 async 属性,script 将立即获取(下载)并执行,然后才继续后面的处理,这期间阻塞了浏览器的后续处理。

2. 如果有 async 属性,那么 script 将被异步下载并执行,同时浏览器继续后续的处理。

3. HTML4中就有了defer属性,它提示浏览器这个 script 不会产生任何文档元素(没有document.write),因此浏览器会继续后续处理和渲染。

4. 如果没有 async 属性 但是有 defer 属性,那么script 将在页面parse之后执行。

5. 如果同时设置了二者,那么 defer 属性主要是为了让不支持 async 属性的老浏览器按照原来的 defer 方式处理,而不是同步方式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值