目前项目中部分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:最好不要卡浏览器
应该可以用sea.js吧?
我试试
@蓝风»: 其实不管是document.write()还是document.createElement('<script>'),加载js文件都是异步的,只不过seajs提供了回调机制,把你需要执行的代码放到回调函数中就行了。
比如某些浏览器支持script标签的onload事件,IE则是onreadystatechange事件
@ThreeTree: 现在无法使用回调机制, boot.js文件是动态加载需要的文件,而页面上可能会存在编写的代码,编写的这些代码是客户自己编写的,而且大量页面已经存在,无法一一修改 头疼
@蓝风»: 如果你只是动态加载外部js文件,根本不需要回调函数。回调函数是用来加载完相应的js文件再去执行的js代码。如果你所有的代码都在外部js文件中,就不需要回调函数。
@蓝风»: 这完全是工程上的问题了。
1.比如jquery文件是肯定需要引用的,可以直接使用script标签引用。就没有必要动态加载了。
2.如果一段代码A依赖于b.js;c.js;d.js;等等,可以使用seajs动态加载,然后把A写在回调函数里。你的问题在于你把A分成了好几部分,那么每一部分都需要使用seajs,每一部分代码都要写在回调函数里。实际上这些代码就不应该分成若干部分的,就算是由多个人开发也不应该。
3.实在不行就不要动态加载了,把所有的js文件都引用上。
4.如果说这些js文件不能全部引用,存在冲突,比如是多版本的js代码。那就是用服务器端判断当前文件应该加载哪些js文件。直接引用需要的js文件。
@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毫秒的延迟,刚好此处用来"延迟"
@蓝风»: 我也做了下测试,发现自己想当然了。重新说下结论。
1. document.write()这种方式加载js脚本,具有一定的同步性质。具体表现在不同script标签之间是同步执行的;自己所在的script标签内部则是异步加载的。所以你这里观察到的现象就是第一个boot.js输出时undefined,其他都是function。这种同步和你说的300-400毫秒的延迟是没有关系的。
而如果是采用document.ceateElement('script')这种个方式,完全就是异步加载的,所有情况都是输出undefined。
2. 我的测试环境是chrome浏览器,在其他环境下未必是这样。
3. 所以最好还是采用回调机制是最好的
@ThreeTree:
1. 300-400的延时是想看看在这一"延时"过程中,后面的javascript代码有没有执行, 现在看来,boot.js内的代码执行了(结果是 undefined),但其余的并没有执行,等jquery文件加载完毕、解释执行后,后面的才执行
2.chrome刚测试过,结果一样
3. 回调是最好的,最保险,但现在项目的实际情况无法回调,硬伤
网上异步加载的库一堆,可惜我们目前环境没法用, 备用,以后的项目再用
额外的收获:通过这次,对于javascript的单线程 事件循环 又加深了了解
sea.js reauire.js lab.js等都尝试了下
document.write怎么个异步加载?
_WriteJs = function (path) { document.write('<script src="' + path + '" type="text/javascript"></script>'); }
目前是这样
@蓝风»: 这个不应该是随机的哇,而且建议你用createElement('script),然后append的方式添加。
直接seajs