script onload/onerror with IE(for lazy loading) problems

守給你的承諾、 提交于 2019-12-03 15:34:31

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 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.

    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:

  • file1 with load time of 4s
  • file2 with a 500 error
  • file3 with 1s of loading

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.

If you know a better way or if you know errors that may occur in this implementation please reply! Thanks!

nozer0
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. In fact, loaded will be triggered in situations loading error script or the first time to load correct script.

You can append src with random query string to disable the cache, then check the readyState.

ignore the junk below. the nextSibling thing was a result of being in the debugger and wasn't really reproducible in the real world. instead, i would have to recommend checking out www.requirejs.org

it provides a method that is about as close to an include or import statement as you could find in js.

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;

like i said i don't know WHY nextSibling is null on a 404'd attempt, but if the js url was correct, nextSibling had a value.

Yuri Izgarshev

Try this one: https://stackoverflow.com/a/18840568/2785975. Here the problem for IE7-8 with onerror event is described and decision is shown.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!