同步加载与异步加载

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

先说下我碰到的问题:项目要接入到支付宝城市服务中,但是安卓和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 方式处理,而不是同步方式。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值