异步加载脚本保持执行顺序

首先是外部脚本和行内脚本,对于异步加载的脚本,会导致竞争状态,使得出现未定义的错。

采用Script Dom技术测试:

代码:

<script type="text/javascript">

var scriptElem = document.createElement(‘script‘);
  scriptElem.src = "js/jquery-2.1.1.js";

document.getElementsByTagName(‘head‘)[0].appendChild(scriptElem);

</script>

<script type="text/javascript">

function test(){

$("#test").addClass(‘class_name‘); }

test();

</script>

运行结果:

以下几种方式解决该问题:

1.硬编码回调

将test方法的执行定义在外部脚本(即调用的脚本),该方法不灵活,如果调用的是第三方脚本的话,更加麻烦。此处不显示例子。

2.Window onload

通过监听window的onload事件来触发行内代码的执行。只要确保外部脚本在window。Onload之前下载执行就可以保持执行顺序。

运行结果:

代码:

function test(){

$("#test").addClass(‘class_name‘);

}

if(window.addEventListener){

window.addEventListener("load", test, false);

}else if(window.attachEvent){

window.attachEvent("onload",test);

}

缺点:1.必须确保异步脚本是通过阻塞onload事件的方式加载的。

         2.如果页面有更多的资源,那么外部脚本可能在onload时间出发之前早就完成加载,一般来说,行内脚本最好在外部脚本下载和执行完成之后立即调用。

3.定时器:

采用轮询方法来抱着在行内脚本执行之前所依赖的外部脚本已经加载。

运行结果:

代码:

function test(){

$("#test").addClass(‘class_name‘);

console.log(index);

}

var index = 0;

function initTimer(){

if("undefined" === typeof($)){

index++;

setTimeout(initTimer,300)

}else{

test();

}

}

initTimer();

缺点:如果在setTimeout方法中设置的时间太小,会造成额外的开销。设置太大会导致和windon.onload的方法一样,脚本加载完成无法立即执行行内脚本。另外,如果脚本出错,轮询会无限进行下去。

4.Script onload

前面提到的整合技术会增加页面的脆弱性、延迟和开销,通过监听脚本的onload事件可以解决这些问题。

运行结果:

代码:

function test(){

$("#test").addClass(‘class_name‘);

}

var scriptElem = document.createElement(‘script‘);

scriptElem.src = "js/jquery-2.1.1.js";

scriptElem.onloadDone = false;

scriptElem.onload = function(){

scriptElem.onloadDone = true;

test();

}

scriptElem.onreadyStatechange  = function(){

if(("loaded" === scriptElem.readyState || "complete" === scriptElem.readyState) && !scriptElem.onloadDone){

scriptElem.onloadDone = true;

test();

}

}

document.getElementsByTagName(‘head‘)[0].appendChild(scriptElem);

优点:维护简单,事件处理也简单,整合异步加载外部脚本和行内脚本的首选。

5.降级使用script标签:

即用一个标签即包含外部脚本,又使用行内脚本,如下:

<script src=" js/jquery-2.1.1.js "  >

function test(){

$("#test").addClass(‘class_name‘);

}

</script>

由于浏览器并不支持这种模式,所以需要在脚本的内部增加代码来执行行内脚本,找到该脚本,并用eval执行其内容。如下:

var scripts = document.getElementsByTagName(‘script‘);

var cntr = scripts.length;

while(cntr--){

var curScript = scripts[cntr-1];

if(-1 != curScript.src.indexOf("js/jquery-2.1.1.js")){

eval(curScript.innerHTML);

break;

}

cntr--;

}

此处不给出例图,具体代码如下:

function test(){

$("#test").addClass(‘class_name‘);

}

var scriptElem = document.createElement(‘script‘);

scriptElem.src = "js/jquery-2.1.1.js";

if(-1 != navigator.userAgent.indexOf("Opera")){

scriptElem.innerHTML = "test()";

}else{

scriptElem.text = "test()";

}

document.getElementsByTagName(‘head‘)[0].appendChild(scriptElem);

优点:技术优雅简洁,开销最小。

缺点:需要修改外部脚本,对第三方库不适用。

时间: 2024-10-12 10:55:22

异步加载脚本保持执行顺序的相关文章

高性能网站优化-确保异步加载脚本时保持执行顺序

<高性能网站建设进阶指南> 脚本如果按照常规方式加载,不仅会阻塞页面中其他内容的下载,还会阻塞脚本后面所有元素的渲染.异步加载脚本可以避免这种阻塞现象,从而提高页面加载速度.但是性能的提升是要付出代价的.代码的异步执行可能会出现竞争状态.简单地说就是页面内部的脚本需要的标示符如果是在外部文件中定义的,而当外部文件异步加载的时候,如果没有保证外部文件和内部脚本执行顺序,很有可能会出现未定义标示符的错误 当异步加载的外部脚本与行内脚本之间存在代码依赖时,就需要通过一种保证执行顺序的方法来整合这两个

Javascript在页面加载时的执行顺序【转】

一.在HTML中嵌入Javasript的方法 直接在Javascript代码放在标记对<script>和</script>之间 由<script />标记的src属性制定外部的js文件 放在事件处理程序中,比如:<p onclick="alert('我是由onclick事件执行的Javascript')">点击我</p> 作为URL的主体,这个URL使用特殊的Javascript:协议,比如:<a href="

异步加载脚本和样式

<script>         window.onload = function () {             loadScriptURL('script/head.js')             loadScriptcode('alert("hahaha");');             loadStyleURL('a.css');             var csscode = '#box{background:red}';             loa

WebKit 中异步加载脚本(Running scripts in WebKit)- 大大提升界面呈现速度

WebKit 中异步加载脚本(Running scripts in WebKit)- 大大提升界面呈现速度 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. Running scripts in

浅谈Html的内容加载及JS执行顺序

同事跟我说他用jQuery取不到页面上隐藏元素input的值,他的html页面大概内容如下. <!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script type="text/javascript"

Javascript 异步加载详解(转)

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续

Javascript 异步加载详解

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续

javascript异步加载详解(转)

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续

[转载]Javascript 同步异步加载详解

http://handyxuefeng.blog.163.com/blog/static/4545217220131125022640/ 本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yo