首页 新闻 会员 周边

动态 "同步" 加载javascript

0
悬赏园豆:15 [已解决问题] 解决于 2015-08-30 22:33

      目前项目中部分javascript需要动态引入,实现方式是,编写一个javascript文件boot.js,html页面引用,在boot.js文件中引入其余的N个脚本文件,      boot.js内部使用的方式是 document.write ,但此方式为异步加载,比如加载jquery文件,由于异步,后面经常遇到找不到jquery问题

      随后适用了 labjs.js文件,可以确保boot.js引用的N多个脚本按照需求,分组顺序加载,确保后面的脚本文件在前面脚本加载完成后再执行,分组内的还是异步加载,这个赞...但,html页面boot.js后面还有调用类似jquery的脚本,然后...还是找不到对象

      有没有什么好的办法? 或者在加载过程中来个sleep.阻止继续执行,直至boot.js加载的javascript文件加载完毕再解析html文档

PS:最好不要卡浏览器

蓝风»的主页 蓝风» | 初学一级 | 园豆:21
提问于:2015-08-25 11:41
< >
分享
最佳答案
0

应该可以用sea.js吧?

收获园豆:15
ThreeTree | 小虾三级 |园豆:1490 | 2015-08-25 12:52

我试试

蓝风» | 园豆:21 (初学一级) | 2015-08-25 14:45

@蓝风»: 其实不管是document.write()还是document.createElement('<script>'),加载js文件都是异步的,只不过seajs提供了回调机制,把你需要执行的代码放到回调函数中就行了。

比如某些浏览器支持script标签的onload事件,IE则是onreadystatechange事件

ThreeTree | 园豆:1490 (小虾三级) | 2015-08-26 18:13

@ThreeTree: 现在无法使用回调机制, boot.js文件是动态加载需要的文件,而页面上可能会存在编写的代码,编写的这些代码是客户自己编写的,而且大量页面已经存在,无法一一修改 头疼

蓝风» | 园豆:21 (初学一级) | 2015-08-26 20:27

@蓝风»: 如果你只是动态加载外部js文件,根本不需要回调函数。回调函数是用来加载完相应的js文件再去执行的js代码。如果你所有的代码都在外部js文件中,就不需要回调函数。

ThreeTree | 园豆:1490 (小虾三级) | 2015-08-27 09:13

@蓝风»: 这完全是工程上的问题了。

1.比如jquery文件是肯定需要引用的,可以直接使用script标签引用。就没有必要动态加载了。

2.如果一段代码A依赖于b.js;c.js;d.js;等等,可以使用seajs动态加载,然后把A写在回调函数里。你的问题在于你把A分成了好几部分,那么每一部分都需要使用seajs,每一部分代码都要写在回调函数里。实际上这些代码就不应该分成若干部分的,就算是由多个人开发也不应该。

3.实在不行就不要动态加载了,把所有的js文件都引用上。

4.如果说这些js文件不能全部引用,存在冲突,比如是多版本的js代码。那就是用服务器端判断当前文件应该加载哪些js文件。直接引用需要的js文件。

ThreeTree | 园豆:1490 (小虾三级) | 2015-08-27 13:19

@ThreeTree: 我重新测试了下,

html:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta charset="utf-8" />
    <script src="Scripts/boot.js"></script>
    <script src="Scripts/JavaScript.js"></script>
    <script>
        console.log("head  " + typeof jQuery);
    </script>

</head>
<body>
    <script>
        console.log("body  " + typeof jQuery);
    </script>
</body>
</html>

其中:boot.js

_WriteJs = function (path) { document.write('<script src="' + path + '" type="text/javascript"></sc' + 'ript>'); }

_WriteJs("https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js");
_WriteJs("Scripts/JavaScriptInBoot.js");

console.log(
"boot.js" + typeof jQuery);

 

javascripts.js

console.log("js  " + typeof jQuery);

 

JavaScriptInBoot.js

console.log("JavaScriptInBoot.js  " + typeof jQuery);

 

最终的结果: firefox40/ ie11下结果一样,为:

boot.js  undefined

JavaScriptInBoot.js function
js  function
head  function
body  function

由此推断出, boot.js文件内部执行 document.write..后,再立即执行涉及jquery的代码会报错

但是在html中,boot.js文件后的代码或者代码文件的执行不受影响.

这个结果基本上是我想要的结果,尽管boot.js内部手写代码会出问题,这个可以避免

 

补充: 调用google的jquery我这边会有300-400毫秒的延迟,刚好此处用来"延迟"

蓝风» | 园豆:21 (初学一级) | 2015-08-27 14:20

@蓝风»: 我也做了下测试,发现自己想当然了。重新说下结论。

1. document.write()这种方式加载js脚本,具有一定的同步性质。具体表现在不同script标签之间是同步执行的;自己所在的script标签内部则是异步加载的。所以你这里观察到的现象就是第一个boot.js输出时undefined,其他都是function。这种同步和你说的300-400毫秒的延迟是没有关系的。

而如果是采用document.ceateElement('script')这种个方式,完全就是异步加载的,所有情况都是输出undefined。

2. 我的测试环境是chrome浏览器,在其他环境下未必是这样。

3. 所以最好还是采用回调机制是最好的

ThreeTree | 园豆:1490 (小虾三级) | 2015-08-27 15:32

@ThreeTree: 

1. 300-400的延时是想看看在这一"延时"过程中,后面的javascript代码有没有执行, 现在看来,boot.js内的代码执行了(结果是 undefined),但其余的并没有执行,等jquery文件加载完毕、解释执行后,后面的才执行

2.chrome刚测试过,结果一样

3. 回调是最好的,最保险,但现在项目的实际情况无法回调,硬伤

网上异步加载的库一堆,可惜我们目前环境没法用, 备用,以后的项目再用

 

额外的收获:通过这次,对于javascript的单线程 事件循环 又加深了了解

 sea.js reauire.js lab.js等都尝试了下

蓝风» | 园豆:21 (初学一级) | 2015-08-27 16:04
其他回答(2)
0

document.write怎么个异步加载?

幻天芒 | 园豆:37175 (高人七级) | 2015-08-25 13:16
_WriteJs = function (path) { document.write('<script src="' + path + '" type="text/javascript"></script>'); }

目前是这样

支持(0) 反对(0) 蓝风» | 园豆:21 (初学一级) | 2015-08-25 14:44

@蓝风»: 这个不应该是随机的哇,而且建议你用createElement('script),然后append的方式添加。

支持(0) 反对(0) 幻天芒 | 园豆:37175 (高人七级) | 2015-08-25 15:44
0

直接seajs

powerixao | 园豆:401 (菜鸟二级) | 2015-08-27 12:00
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册