[英]script onload/onerror with IE(for lazy loading) problems
I'm rebuilding my lazy loader module to accept asyncronus request but i have a BIG problem: 我正在重建我的惰性加载程序模块以接受异步请求,但是我遇到了一个大问题:
internet explorer don't support script.onload/onerror!!! Internet Explorer不支持script.onload / onerror !!!
The old script did globally eval the target script source read with an ajax sync call, it works very well,it's cross browser and i can make it async editing 1 variable but it's very tricky to debug(ALL the source code is executed in one single line and the browser gives not to much infos about the errors,dividing the code by line with a regexp is IMPOSSIBLE because js have blocks with infinite depth and regexp are simply not good at this). 旧脚本在全局范围内评估了通过ajax同步调用读取的目标脚本源,它工作得很好,它是跨浏览器,我可以使其异步编辑1个变量,但是调试起来非常棘手(所有源代码都在一个代码中执行行和浏览器没有提供太多有关错误的信息,使用regexp逐行划分代码是不可能的,因为js具有无限深度的块,而regexp根本不擅长此操作)。
This is the code that i use to create the script(a classic): 这是我用来创建脚本的代码(经典):
var script = document.createElement('script');
script.type = 'text/javascript';
script.src =name;
script.name =name;
script.async = true;
script.onload=<my_onload_code>;
script.onerror=<my_onerror_code>;
it won't work on IE because it doesen't support onload and onerror with the script; 它不适用于IE,因为它不支持脚本的onload和onerror。
the code below is a fix but works only if the script isn't async 下面的代码是一个修复程序,但仅在脚本不异步时有效
if(script.onreadystatechange!==undefined)//only IE T_T
script.onreadystatechange = function() {
if (script.readyState == 'loaded')//ERROR LOADING
<my_onerror_code>;
else
if(script.readyState == 'complete')//loaded
<my_onload_code>;
};
i can test it every X milliseconds until the script is loaded but it's an ugly solution and i want to avoid it. 我可以每X毫秒测试一次,直到脚本加载完毕,但这是一个丑陋的解决方案,我想避免使用它。
EDIT: this is the code i tryed to check every X ms if the script is loaded, it's not that bad and it works better than ajax;the problem is that i can't know if the script is loaded with success or with error(onload or onerror). 编辑:这是我试图在脚本加载后每隔X ms进行检查的代码,它还不错,并且比ajax更好;问题是我不知道脚本是成功加载还是错误加载( onload或onerror)。
var script = document.createElement('script');
script.type = 'text/javascript';
script.src =name;
script.name =name;
script.async = true;
script.onload=function(){Lazy_loader.onload(this);};
script.onerror=function(){Lazy_loader.onerror(this);};
if(script.onreadystatechange!==undefined){//ie fix T_T
script.timer=setInterval(function(){
if (script.readyState == 'loaded' || script.readyState == 'complete')}//ERROR LOADING
if(LOADED???)//loaded
Lazy_loader.onload(script);
else
Lazy_loader.onerror(script);
clearInterval(script.timer);
}
},100);
}
document.getElementsByTagName('head')[0].appendChild(script);
i tryed to use addEventListener/attachEvent functions but it didn't seem to work(even using addEvent functions from the web) 我尝试使用addEventListener / attachEvent函数,但似乎没有用(即使使用网络上的addEvent函数)
summarizing the options seems to be: 总结选项似乎是:
Hope that's not too much! 希望不要太多! Thanks.
谢谢。
This is one solution: if it's IE i'll simply load the text with an async ajax call and then set the script.text to the loaded data. 这是一种解决方案:如果是IE,我将使用异步ajax调用简单地加载文本,然后将script.text设置为已加载的数据。 IE seems to lock onload and onerror(for security reasons?)and not script.text(some other browsers may not allow it for security resons to prevent XSS attacks like on iframes),i don't know why microsoft can't simply respect standards,i simply hate ie and "tricks" to fix theyr's desing problems.
IE似乎锁定了onload和onerror(出于安全原因?)而不是script.text(某些其他浏览器可能出于安全考虑而阻止了它,以防止像iframe上的XSS攻击),我不知道为什么微软不能简单地尊重标准,我只是讨厌ie和“技巧”来解决他们的设计问题。
var script = document.createElement('script');
script.type = 'text/javascript';
//---start IE fix---
if(window.ActiveXObject){//ie fix T_T
var xmlhttp=null;
try {
xmlhttp = new XMLHttpRequest();
}catch(e){
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
xmlhttp.onreadystatechange = function() {
try{
if(this.done!==undefined)
return;
if(this.status >= 200 && this.status < 300){//loaded
this.done=true;
script.text=this.responseText;
document.getElementsByTagName('head')[0].appendChild(script);
Lazy_loader.onload({name:name});
}
if(this.status >= 400){
this.done=true;
Lazy_loader.onerror({name:name});
}
}catch(e){}
};
xmlhttp.open('get',name,true);
xmlhttp.send(null);
}
else{//browser that support script.onload/onerror
script.src =name;
script.name =name;
script.async = true;
script.onload=function(){Lazy_loader.onload(this);};
script.onerror=function(){Lazy_loader.onerror(this);};
document.getElementsByTagName('head')[0].appendChild(script);
}
//---end IE fix---
this works well on most browsers(IE/chrome/firfox tested for now)and i tested loading 3 files: 这在大多数浏览器上都运行良好(目前已测试IE / chrome / firfox),我测试了加载3个文件:
and they're loaded in a total of 40XX ms in all browsers(some extra time is taken by the browser to call the onload/onerror script),i can also(with my lazy loader script)simulate a sync loading executing code only after all files in queue are loaded. 并且它们在所有浏览器中总共加载了40XX毫秒(浏览器花费了一些额外的时间来调用onload / onerror脚本),我也可以(使用我的惰性加载器脚本)模拟仅在队列中的所有文件都已加载。
If you know a better way or if you know errors that may occur in this implementation please reply! 如果您知道更好的方法,或者您知道此实现中可能发生的错误,请回复! Thanks!
谢谢!
script.onreadystatechange = function() {
if (script.readyState == 'loaded')//ERROR LOADING
<my_onerror_code>;
else if(script.readyState == 'complete')//loaded
<my_onload_code>;
};
I have to say that regardless whether async
is set or not, using readyState = 'loaded'
to check error is not enough. 我必须说,无论是否设置了
async
,使用readyState = 'loaded'
来检查错误是不够的。 In fact, loaded
will be triggered in situations loading error script or the first time to load correct script. 事实上,
loaded
会在加载错误的脚本或第一次加载正确的脚本的情况下被触发。
You can append src
with random query string to disable the cache, then check the readyState
. 您可以在
src
后面附加随机查询字符串以禁用缓存,然后检查readyState
。
Try this one: https://stackoverflow.com/a/18840568/2785975 . 试试这个: https : //stackoverflow.com/a/18840568/2785975 。 Here the problem for IE7-8 with onerror event is described and decision is shown.
此处描述了带有onerror事件的IE7-8的问题并显示了决策。
ignore the junk below. 忽略下面的垃圾。 the nextSibling thing was a result of being in the debugger and wasn't really reproducible in the real world.
nextSibling的原因是在调试器中的结果,并且在现实世界中并不是真正可复制的。 instead, i would have to recommend checking out www.requirejs.org
相反,我将不得不建议查看www.requirejs.org
it provides a method that is about as close to an include or import statement as you could find in js. 它提供的方法与js中包含的include或import语句差不多。
this is a totally goofball solution, and i will be following this thread for comments about why this works, but here goes how i fixed this without a timer. 这是一个完全愚蠢的解决方案,我将关注这个主题,以评论其工作原理,但是这里介绍了如何在没有计时器的情况下解决此问题。
var url = load_obj.url;
var callback = load_obj.callback;
var head = document.getElementsByTagName('head')[0];
var appendage;
var complete = false;
appendage = document.createElement('script');
appendage.type = 'text/javascript';
appendage.onload = appendage.onreadystatechange = function() {
if (!complete && (!this.readyState || this.readyState === 'complete' || (this.readyState === 'loaded' && this.nextSibling != null))) {
console.log('loaded via all');
complete = true;
if (callback)
callback();
//remove listeners
appendage.onload = appendage.onreadystatechange = null;
} else if (this.readyState === 'loaded' && this.nextSibling == null) {
console.log('error via ie');
}
appendage.onerror = function() {
console.log('error via everything else');
}
appendage.src = url;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.