Javascript 带有IE(用于延迟加载)问题的脚本onload/onerror

Javascript 带有IE(用于延迟加载)问题的脚本onload/onerror,javascript,internet-explorer,asynchronous,lazy-loading,Javascript,Internet Explorer,Asynchronous,Lazy Loading,我正在重建我的惰性加载程序模块以接受asyncronus请求,但我有一个大问题: internet explorer不支持脚本。onload/onerror 旧脚本使用ajax同步调用全局评估读取的目标脚本源, 它工作得很好,它是跨浏览器的,我可以使它异步编辑1个变量,但调试起来非常棘手(所有源代码都是在一行中执行的,浏览器没有提供太多关于错误的信息,用regexp将代码逐行分割是不可能的,因为js有无限深度的块,而regexp根本不擅长这一点) 这是我用来创建脚本的代码(经典): 我尝试使用a

我正在重建我的惰性加载程序模块以接受asyncronus请求,但我有一个大问题:
internet explorer不支持脚本。onload/onerror

旧脚本使用ajax同步调用全局评估读取的目标脚本源, 它工作得很好,它是跨浏览器的,我可以使它异步编辑1个变量,但调试起来非常棘手(所有源代码都是在一行中执行的,浏览器没有提供太多关于错误的信息,用regexp将代码逐行分割是不可能的,因为js有无限深度的块,而regexp根本不擅长这一点)

这是我用来创建脚本的代码(经典):

我尝试使用addEventListener/attachEvent函数,但似乎不起作用(甚至使用web上的addEvent函数)

总结这些选择似乎是:

  • 使用AJAX和全局eval加载脚本(调试地狱)
  • 仅在IE中使用AJAX和全局评估(可能是一种解决方案,我不使用IE)
  • 仅当脚本包含错误时才使用AJAX和全局评估(我需要检查计时问题,因为我的代码“模拟”同步代码,即使调用是异步的)
  • 每X次测试script.onreadystatechange(仅在IE上),直到加载为止(丑!!!)
  • 使用window.onload:AVOID,它需要对所有页面收费,我需要在只启动一个脚本时调用它(请参阅endpage上的详细信息)
  • 在每个脚本的源代码上添加一个代码(避免像尾页上所说的那样)
  • 修复IE的script.onload(使用addEventListener/attachEvent?!?)

请注意:
我不想使用window.onload,因为它只有在加载所有页面时才会触发,我需要在只加载目标脚本时触发它(我的延迟加载脚本要复杂得多,所以请不要问为什么);
我不想使用任何第三方库(如jquery、prototype等)
我甚至不想编辑目标脚本源代码(比如在使用JSPON或添加脚本以警告脚本已加载时)

希望不要太多! 谢谢。

这是一个解决方案: 如果是IE,我只需使用异步ajax调用加载文本,然后将script.text设置为加载的数据。 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---
var script=document.createElement('script');
script.type='text/javascript';
//---启动IE修复--
if(window.ActiveXObject){//ie修复
var xmlhttp=null;
试一试{
xmlhttp=新的XMLHttpRequest();
}捕获(e){
试一试{
xmlhttp=新的ActiveXObject(“Msxml2.xmlhttp”);
}捕获(e){
xmlhttp=新的ActiveXObject(“Microsoft.xmlhttp”);
}
}  
xmlhttp.onreadystatechange=函数(){
试一试{
if(this.done!==未定义)
返回;
如果(this.status>=200&&this.status<300){//loaded
这个。完成=正确;
script.text=this.responseText;
document.getElementsByTagName('head')[0].appendChild(脚本);
Lazy_loader.onload({name:name});
}
如果(this.status>=400){
这个。完成=正确;
Lazy_loader.onerror({name:name});
}
}捕获(e){}
};
open('get',name,true);
xmlhttp.send(空);
}
else{//支持script.onload/onerror的浏览器
script.src=名称;
script.name=名称;
script.async=true;
script.onload=function(){Lazy_loader.onload(this);};
script.onerror=function(){Lazy_loader.onerror(this);};
document.getElementsByTagName('head')[0].appendChild(脚本);
}
//---结束IE修复---
这在大多数浏览器上运行良好(IE/chrome/firfox目前已测试),我测试了加载3个文件:

  • 文件1,加载时间为4s
  • file2有一个500错误
  • 文件3,加载时间为1s
在所有浏览器中,它们的加载时间总共为40XX毫秒(浏览器调用onload/onerror脚本需要一些额外的时间),我还可以(使用我的延迟加载脚本)在加载队列中的所有文件后模拟同步加载执行代码

如果您知道更好的方法,或者您知道此实现中可能出现的错误,请回复!
谢谢!

忽略下面的垃圾。下一个隐藏的东西是在调试器中的结果,在现实世界中不是真正可复制的。相反,我建议您访问www.requirejs.org

它提供了一种方法,该方法与js中的include或import语句非常接近

这是一个完全愚蠢的解决方案,我将按照这条线索来评论它为什么会起作用,但下面是我如何在没有计时器的情况下修复它的。
var url=load_obj.url;
var callback=load_obj.callback;
var head=document.getElementsByTagName('head')[0];
变种附属物;
var complete=false;
appendage=document.createElement('script'); appendage.type='text/javascript'; appendage.onload=appendage.onreadystatechange=function(){ 如果(!complete&&(!this.readyState | | this.readyState==='complete'| | |(this.readyState==='loaded'&&this.nextSibling!=null))){ console.log('loaded via all'); 完整=正确; 如果(回调) 回调(); //删除侦听器 appendage.onload=appendage.onreadystatechange=null; }else if(this.readyState==
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>;

            };
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);
    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---
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;
script.onreadystatechange = function() {
    if (script.readyState == 'loaded')//ERROR LOADING
        <my_onerror_code>;
    else if(script.readyState == 'complete')//loaded
        <my_onload_code>;

};