js的并行加载以及顺序执行
重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦。
现在现总结下并行加载多个js的方法:
1,对于动态createElement('script')的方式,对所有浏览器都是异步并行加载的。这里所说的并行不仅仅指的是
js并行加载,也包括js和其他资源比如图片,iframe的加载。但是此种方式在Firefox的2.0 3.0 3.1版本和opera 9.63
下是可以顺序执行的。但是由于Kyle的提议,现代浏览器都可以通过对动态创建的script元素设置属性async=false来使
js顺序执行。
2,可以通过document.write('<script>')的方式来并行加载(IE,现代浏览器)和顺序执行。
3,通过xhr加载js。但是有了同源的限制,因此对于外部js文件或者cdn上的js就无能为力。
已经有些大牛比如之前提到的Kyle已经提供了兼容个浏览器的标准库,项目名称是 LABjs。
自己写了一个简单的插件,目前并没有在IE6,7上测试。
if(!asyncHelper) var asyncHelper = {};
asyncHelper.cache = []; //存储获取到的js对象
asyncHelper.createAjax = (function(){
if('XMLHttpRequest' in window){
return function(){
return new XMLHttpRequest();
}
}else{
var i= 0,len, fns = [function(){return new ActiveXObject('Microsoft.XMLHTTP')},function(){return new ActiveXObject('Msxml2.XMLHTTP')},
function(){return new ActiveXObject('Msxml2.XMLHTTP.3.0')},function(){return new ActiveXObject('Msxml2.XMLHTTP.6.0')}];
for(len = fns.length;i<len;i++){
try{
fns[i]();
return fns[i];
break;
}catch (e){
}
}
}
})();
//功能函数,异步xhr加载js,并行无序加载js和其他资源,需要进行顺序控制;而且受同源限制,
//无法使用cdn或外部引用js
asyncHelper._loadJsWithXHR = function(url,fn,inOrder){
inOrder = inOrder || true; //默认顺序加载
var jsObj = {file: null,isLoaded:false,callback: fn},xhr,
i,len;
asyncHelper.cache.push(jsObj);
xhr = this.createAjax();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
try{
if(xhr.status >=200 && xhr.status < 300 || xhr.status == 304){
jsObj.file = xhr.responseText; // 返回的js存入对象中
if(inOrder){
for(i=0,len=asyncHelper.cache.length;i<len;i++){
if(!asyncHelper.cache[i].file){
//避免重复解析已加载过得js文件
//从缓冲汇总删除已经加载的文件
if(i>0){
asyncHelper.cache.splice(0,i);
}
break;
}else{
//Function相当于全局eval,不会改变作用域链
new Function(asyncHelper.cache[i].file)();
fn && fn(); //执行回调函数
if(i == len-1){
asyncHelper.cache = []; //清空缓存
}
}
}
}else{
if(jsObj.file){
eval(jsObj.file);
fn();
}
}
}
}catch (loadError){
setTimeout(function(){
throw(new Error('loading with XHR response error--' + loadError))
},0);
}
}
};
xhr.open('get',url);
xhr.setRequestHeader('X-Request-With','XMLHttpRequest');
xhr.send(null);
};
//通过创建script元素来异步加载js,支持跨域。在firefox,opera下也是顺序加载。
asyncHelper._loadJsWithDOMElement = function(url,fn){
var dom = document.createElement('script');
dom.type = 'application/javascript';
dom.async = false;
dom.src = url;
dom.isloaded = false;
//执行回调函数,IE下使用onreadystatechange,w3c使用onload
if('onload' in dom){
dom.onload = fn;
}else{
dom.onreadystatechange = function(){
if((dom.readyState == 'loaded' || dom.readyState == 'complete') &&
!dom.isloaded){
fn();
dom.isloaded = true;
}
}
}
document.getElementsByTagName('head')[0].appendChild(dom);
}
//通过document.write插入script来进行并行加载脚本。gte IE8以及opera支持。
//全部浏览器支持此种方式的顺序加载js
asyncHelper._loadJsWithScriptTag = function(url,fn){
document.writeln('<script type="application/javascript" src="' +
url +'"><\/script>');
//给window绑定onload事件
if(window.addEventListener){
window.addEventListener('load',fn,false);
}else{
window.attachEvent('onload',function(){
fn.call(this,window.event);
})
}
}
//暴露外部接口,加载单个js文件
asyncHelper.loadScript = function(url,fn){
this._loadJsWithDOMElement(url,fn);
}
//加载多个js文件
asyncHelper.loadScripts = function(urls,fn){
function isSameDomain(url){
var domain = document.location.protocol + "//" +
document.location.hostname + "/";
if(url.indexOf('http') !== -1 || url.indexOf('https') !== -1){
if(url.indexOf(domain) !== -1){
return true;
}
return false;
}
return true;
}
//如果url同源,则使用xhr加载
var i,len,flag,loadMethod;
for(i=0,len=urls.length;i<len;i++){
if(flag = isSameDomain(urls[i])) continue;
else break;
}
//默认xhr加载
loadMethod = asyncHelper._loadJsWithXHR;
if(!flag){
//firefox opera使用DomElement方式加载,确保顺序性和异步加载
// 经测试,目前最新版本的Firefox亦不支持此特性。
//Firefox 4为了更向HTML5标准看齐,一度在开发者版本中去掉了对动态创建<script>来加载js文件的执行顺序支持:
//<script> elements created using document.createElement() and inserted into a document now behave
// according to the HTML5 specification by default. Scripts with the src attribute
// execute as soon as available (without maintaining ordering) and scripts without
// the src attribute execute synchronously.
//Kyle向WebKit开发团队抗议,提了一个bug,最终得到了如他所愿的支持:
//To make script-inserted scripts that have the src attribute execute in the insertion order,
// set .async=false on them.
if(navigator.userAgent.toLowerCase().indexOf('firefox') != -1 || navigator.userAgent.toLowerCase().indexOf('opera') != -1)
loadMethod = asyncHelper._loadJsWithDOMElement;
else
loadMethod = asyncHelper._loadJsWithScriptTag;
}for(i=0;i<len;i++){
if(i == len - 1){
loadMethod.call(asyncHelper,urls[i],fn);
}else{
loadMethod.call(asyncHelper,urls[i]);
}
}
}
// 示例代码
asyncHelper.loadScripts(['http://libs.baidu.com/jquery/1.9.0/jquery.js','./a.js','./b.js'],function(){console.log('success')})
js的并行加载以及顺序执行的更多相关文章
- js的并行加载与顺序执行
javaScript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能问 ...
- js并行加载,顺序执行
js并行加载,顺序执行 <script>运行脚本或加载外部文件时,会阻塞页面渲染,阻塞其他资源的加载.如果页面中需要加载多个js文件,在古老浏览器中性能会比较糟糕. 因此有了最原始的优化原 ...
- 动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数
动态加载JS文件,并根据JS文件的加载状态来执行自己的回调函数, 在很多场景下,我们需要在动态加载JS文件的时候,根据加载的状态来进行后续的操作,需要在JS加载成功后,执行另一方法,这个方法是依托在加 ...
- JS,Javascript加载与函数执行过程
Js,Javascript加载与函数执行过程 test.html <!DOCTYPE HTML> <html lang="en"> <head> ...
- js中页面加载完成后执行的几种方法及执行顺序
在js和jquery使用中,经常使用到页面加载完成后执行某一方法.通过整理,大概是五种方式(其中有的只是书写方式不一样). 1:使用jQuery的$(function){}; 2:使用jquery的$ ...
- js 文档加载完成之后执行 备用
//文档加载完成之后执行 (function(){ var _globeCallback; window.$$ = function(callback){ _globeCallback = callb ...
- js中页面加载完成后执行的几种方式及执行顺序
1:使用jQuery的$(function){}; 2:使用jquery的$(document).ready(function(){});前两者本质上没有区别,第1种是第2种的简写方式.两个是docu ...
- requirejs:性能优化-及早并行加载
为了提高页面的性能,通常情况下,我们希望资源尽可能地早地并行加载.这里有两个要点,首先是尽早,其次是并行. 通过data-main方式加载要尽可能地避免,因为它让requirejs.业务代码不必要地串 ...
- js顺序加载与并行加载
前端优化过程中常提到js的加载方式,下面说下几种常用的加载方式: 1:head标签内插入<script>标签 <script type="text/javaScript&q ...
随机推荐
- ZOJ1913 Euclid's Game (第一道简单的博弈题)
题目描述: Euclid's Game Time Limit: 2 Seconds Memory Limit: 65536 KB Two players, Stan and Ollie, p ...
- 部署Thomas Kyte 的 runstats 工具
runstats是由Thomas Kyte开发的脚本,该脚本能对做同一件事的两个不同方法进行比较,得出孰优孰劣的结果. 1.授权 SQL> grant select on v_$statname ...
- Ubuntu 14.04--php的安装和配置
更新源列表 打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入root用户的密码"--& ...
- RFID工作流程
读写器通过发射天线发送一定频率的射频信号,² 当射频卡进入发射天线工作区域时产生感应电²流,射频卡获得能量被启动.²²射频卡将自身编码等信息透过卡内天线发送出²去.²²读写器接收天线接收到从 射频卡发 ...
- bzoj 2739 最远点
Description 给你一个N个点的凸多边形,求离每一个点最远的点. Input 本题有多组数据,第一行一个数T,表示数据组数. 每组数据第一行一个数N,表示凸多边形点的个数,接下来N对数,依次表 ...
- 修改sql数据库文件 物理文件名称
-- 允许配置高级选项 EXEC sp_configure 'show advanced options', 1 GO -- 重新配置 RECONFIGURE GO -- 启用xp_cmdshell ...
- python获取当前时间的用法
1.先导入库:import datetime 2.获取当前日期和时间:now_time = datetime.datetime.now() 3.格式化成我们想要的日期:strftime() 比如:“2 ...
- 在Android上使用qemu-user运行可执行文件
在Android上使用qemu-user运行可执行文件 作者:寻禹@阿里聚安全 前言 QEMU简要介绍: QEMU可以解释执行可执行程序.既然QEMU可以解释执行可执行程序,那么QEMU就能够知道执行 ...
- 剑指Offer面试题:20.栈的压入、弹出序列
一.题目:栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1.2.3.4.5是某栈的压栈序列,序列4 ...
- 扩展Bootstrap Tooltip插件使其可交互
最近在公司某项目开发中遇见一特殊需求,请笔者帮助,因此有了本文的插件.在前端开发中tooltip是一个极其常用的插件,它能更好向使用者展示更多的文档等帮助信息.它们通常都是一些静态文本信息.但同事他们 ...