博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LABJS源码浅析
阅读量:6834 次
发布时间:2019-06-26

本文共 5328 字,大约阅读时间需要 17 分钟。

一、关于LABjs的简单介绍

作者:Kyle Simpson

作用:动态并行加载脚本文件 以及 管理加载脚本文件的执行顺序

官网:

 

二、关于LABjs的使用

以下实例原文链接:

更全更详细说明:

实例1:

$LAB.script("script1.js")    .script("script2.js")    .script("script3.js")    .wait(function(){
// 等待所有script加载完再执行这个代码块 script1Func(); script2Func(); script3Func(); });

 

实例2:

$LAB.script({ src:"script1.js", type:"text/javascript"})    .script("script2.js")    .script("script3.js")    .wait(function(){
// 等待所有script加载完再执行这个代码块 script1Func(); script2Func(); script3Func();} );

实例3:

$LAB.script("script1.js","script2.js","script3.js")    .wait(function(){
// 等待所有script加载完再执行这个代码块 script1Func(); script2Func(); script3Func(); });

 

实例4:

$LAB.script(["script1.js","script2.js"],"script3.js")    .wait(function(){
// 等待所有script加载完再执行这个代码块 script1Func(); script2Func(); script3Func(); });

 

实例5:

$LAB.script("script1.js")    .wait()    // 空的wait()只是确保script1在其他代码之前被执行    .script("script2.js")    // script2 和 script3 依赖于 script1    .script("script3.js")    .wait()    // 但是script2 和 script3 并不互相依赖,可以并行下载    .script("script4.js")    //script4 依赖于 script1, script2 及 script3 .wait(function(){script4Func();});

 

实例6:

$LAB.script("script1.js")    // script1, script2, and script3 之间没有依赖关系,     .script("script2.js")    // 所以可以任意顺序执行    .script("script3.js")    .wait(function(){    // 如果需要,这里当然可以执行javascript函数        alert("Scripts 1-3 are loaded!");    })    .script("script4.js")    // 依赖于 script1, script2 及 script3     .wait(function(){script4Func();});

 

实例7:

$LAB.setOptions({AlwaysPreserveOrder:true})// 设置每个脚本之间等待    .script("script1.js")// script1, script2, script3, script4 互相依赖    .script("script2.js")// 并且并行下载后循序执行    .script("script3.js")    .script("script4.js")    .wait(function(){        script4Func();    });

 

实例8:

$LAB.script(function(){        // `_is_IE`的值ie为true ,非ie为false        if(_is_IE){            return"ie.js";    // 如果是ie则这个js会被加载        }else{            return null;    //如果不是ie这个代码就会被略过        }    })    .script("script1.js")   .wait();

 

三、LABjs主要采用加载方式

LABjs里的动态加载脚本文件,是指页面的js脚本执行时,通过多种方法去加载外部的js(主要区别于html页面里,通过<script>标签静态加载的脚本)

动态加载脚本的方式有很多,优缺点不一,此处不赘述,有兴趣的童鞋可以参见本文末尾的参考链接 :)。

LABjs里主要使用了三种技巧,分别为Script ElementXHR Injection以及Cache Trick

首先对这三种加载方式进行简单介绍,第四部分再分析LABjs源码实现里面对着三种方式分别的使用场景

 

Script Element(LABjs默认采用加载方式) 

最常见的脚本动态加载方式,优点很多,包括:1、实现简单 2、可跨域 3、不会阻塞其他资源的加载 等

Opera/Firefox(老版本)下:脚本执行的顺序与节点被插入页面的顺序一致

IE/Safari/Chrome下:执行顺序无法得到保证

注意:

  • 新版本的Firefox下,脚本执行的顺序与插入页面的顺序不一定一致,但可通过将script标签的async属性设置为false来保证顺序执行
  • 老版本的Chrome下,脚本执行的顺序与插入页面的顺序不一定一致,但可通过将script标签的async属性设置为false来保证顺序执行

 

XHR Injection

通过ajax请求加载脚本文件,然后再通过以下方式执行:

  • eval:常见方式
  • XHR injection:创建一个script元素,并将请加载的脚本文件的内容注入

主要限制:无法跨域

 

Cache Trick(强依赖于浏览器的特性实现,不推荐使用)

当你将script元素的type属性设置为浏览器不认识的值,比如"text/cache"、"text/casper"、"text/hellworld"等,不同浏览器的行为如下:

IE/Safari/Chrome(老版本)里:脚本照常加载,但不会执行,假设浏览器没有禁用缓存,加载后的脚本会被浏览器缓存起来,当需要用到的时候,只需要重新创建个script标签,将type设为正确的值,src指向之前请求的文件url即可(相当于从缓存里读文件)

Opera/Firefox:不加载

备注:

  • 强依赖于浏览器的特性实现,有可能随着浏览器特性实现的改变而失效,不推荐使用
  • 新版本的chrome浏览器,将script元素的type设置为非"text/javascript",不会再对脚本文件进行加载

 

四、LABjs里关于脚本加载采用方案的判断

忽略技术细节,通过一段伪代码来描述LABjs里面的实现,大致为:

首先判断是否对请求的脚本进行预加载(是否进行预加载的判断条件看伪代码注释);

如进行预加载,再判断浏览器是否支持真正的预加载;如支持真正的预加载,则预加载之;如否,判断请求的脚本是否跟当前页面同域,如实,采用XHR Injection,如否,采用Cache Trick;

如不进行预加载,判断浏览器支不支持script元素的async属性(见伪代码注释),如是,设置async属性,并请求脚本文件;如否,直接通过script元素加载脚本文件;

if(ifPreloadScript){    //当请求的脚本文件是否进行预加载:1、需要预加载 2、浏览器支持预加载    if(supportRealPreloading){    //如果支持真正的预加载        if(supportPreloadPropNatively){    //支持通过设置script标签的preload属性,实现script的预加载,以及分离加载和执行                                        //Nicholas C. Zakas大神的美好愿望,尚未有浏览器支持:http://www.nczonline.net/blog/2011/02/14/separating-javascript-download-and-execution/            script.onpreload = callback;            script.newPreload = true;            script.src = targetUrl;        }else{            script.onreadystatechange = callback;    //其实就是指IE浏览器,假设指定了script元素的src属性,IE浏览器里会立即加载            script.src = targetUrl;    //即使script元素没有被插入页面,callback为预加载后的回调        }    }    else if(inSameDomain){    //非跨域,采用XHR Injection:请求的脚本与当前页面处于同一个域        xhr = new XMLHttpRequest();    //由于上个判断已经将IE无情地抛弃在这个条件分支之外,所以大胆地用 new XMLHttpRequest()吧        xhr.onreadystatechange = callback;        xhr.open("GET",targetUrl);        xhr.send();    }    else{    //最无奈的后招,Cache Trick,新版chromei已经不支持        script.onload = callback;        script.type = 'text/cache';            script.src = targetUrl;    }}else{    if(canContrlExecutionOrderByAsync){    //如果能够通过script元素的async属性来强制并行加载的脚本顺序执行                                        //kyle大神着力推进的提案,目前已被html5小组接受并放入草案:http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order#My_Solution        script.onload = callback;        script.async = false;    //将script元素的async设为false,可以保证script的执行顺序与请求顺序保持一致        script.src = targetUrl;    }    else{        script.onload = callback;        script.src = targetUrl;        }}

实际上,当你在页面创建一个img节点,并将其src指向一个脚本文件,在部分浏览器里同样能够起到文件预加载的作用,那么LABjs的作者是不是没有想到这一点呢?

不少LABjs的使用者都向kyle提过上面这个问题,key表示:在现有加载策略已经能够满足需求的情况下,不想让LABjs的设计变得更复杂了(非原话)

 

写在后面

此处仅仅简单对LABjs的作用、用法以及内部实现简单介绍了下,关于内部具体源代码实现的分析,留待下一篇文章

如有错漏,请指出 ,如有问题,欢迎回复以及邮件进一步交流 :)

 

参考资料:

oldj:《》

steve souders:

Franky:

大魔I‘m png:

 

后续阅读推荐:

Nicholas C. Zakas大神关于脚本加载的设想:

kyle Simpson关于脚本加载的提案:

kely Simpson关于Firefox某版本去掉脚本执行顺序保证的回应:

转载地址:http://bktkl.baihongyu.com/

你可能感兴趣的文章
Click Button to change the color of TextView
查看>>
oracle preparestmt 插入时间
查看>>
Java系的几种WebServer和ApplicationServer
查看>>
Android之菜单二——上下文菜单
查看>>
JavaScript中onmouseover时如何让鼠标指针变成一个小手状
查看>>
clear:both; 用法 什么时候用
查看>>
三层结构
查看>>
【简报】超棒的拖放式文件上传javascript类库:FileDrop
查看>>
连续子数组的最大和
查看>>
转: Oracle AWR 报告 每天自动生成并发送邮箱
查看>>
solr dataimport 数据导入源码分析(十)总结
查看>>
So easy,JQuery调用WebServices
查看>>
GNU make manual 翻译(四十七)
查看>>
makefile中变量覆盖的小例子
查看>>
所有类型都从Object类型派生
查看>>
关于MFC和android开发上的一些相近地方
查看>>
Linux下rsync的用法
查看>>
c# DataGridView控件的使用
查看>>
TChart的用法
查看>>
DTP语义组分析
查看>>