簡體   English   中英

IE的腳本onload / onerror(用於延遲加載)問題

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

我正在重建我的惰性加載程序模塊以接受異步請求,但是我遇到了一個大問題:
Internet Explorer不支持script.onload / onerror !!!

舊腳本在全局范圍內評估了通過ajax同步調用讀取的目標腳本源,它工作得很好,它是跨瀏覽器,我可以使其異步編輯1個變量,但是調試起來非常棘手(所有源代碼都在一個代碼中執行行和瀏覽器沒有提供太多有關錯誤的信息,使用regexp逐行划分代碼是不可能的,因為js具有無限深度的塊,而regexp根本不擅長此操作)。

這是我用來創建腳本的代碼(經典):

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

它不適用於IE,因為它不支持腳本的onload和onerror。
下面的代碼是一個修復程序,但僅在腳本不異步時有效

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

            };

我可以每X毫秒測試一次,直到腳本加載完畢,但這是一個丑陋的解決方案,我想避免使用它。

編輯:這是我試圖在腳本加載后每隔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);

我嘗試使用addEventListener / attachEvent函數,但似乎沒有用(即使使用網絡上的addEvent函數)

總結選項似乎是:

  • 使用AJAX和全局eval加載腳本(調試地獄)
  • 僅對IE使用AJAX和全局評估(可能是一種解決方案,我不使用IE)
  • 僅當腳本包含錯誤時才使用AJAX和全局評估(我需要檢查計時問題,因為即使調用是異步的,我的代碼也“模擬”了同步代碼,因此我需要檢查計時問題)
  • 每X次測試script.onreadystatechange(僅在IE上),直到加載完畢(丑陋!!!)
  • 使用window.onload:避免,它需要對所有頁面收費,我僅在啟動一個腳本時才需要調用它(請參見末頁上的詳細信息)
  • 在每個腳本的源代碼上添加一個代碼(避免在首頁上顯示該代碼)
  • 修復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---

這在大多數瀏覽器上都運行良好(目前已測試IE / chrome / firfox),我測試了加載3個文件:

  • 加載時間為4s的file1
  • file2出現500錯誤
  • 加載1s的file3

並且它們在所有瀏覽器中總共加載了40XX毫秒(瀏覽器花費了一些額外的時間來調用onload / onerror腳本),我也可以(使用我的惰性加載器腳本)模擬僅在隊列中的所有文件都已加載。

如果您知道更好的方法,或者您知道此實現中可能發生的錯誤,請回復! 謝謝!

script.onreadystatechange = function() {
    if (script.readyState == 'loaded')//ERROR LOADING
        <my_onerror_code>;
    else if(script.readyState == 'complete')//loaded
        <my_onload_code>;

};

我必須說,無論是否設置了async ,使用readyState = 'loaded'來檢查錯誤是不夠的。 事實上, loaded會在加載錯誤的腳本或第一次加載正確的腳本的情況下被觸發。

您可以在src后面附加隨機查詢字符串以禁用緩存,然后檢查readyState

試試這個: https : //stackoverflow.com/a/18840568/2785975 此處描述了帶有onerror事件的IE7-8的問題並顯示了決策。

忽略下面的垃圾。 nextSibling的原因是在調試器中的結果,並且在現實世界中並不是真正可復制的。 相反,我將不得不建議查看www.requirejs.org

它提供的方法與js中包含的include或import語句差不多。

這是一個完全愚蠢的解決方案,我將關注這個主題,以評論其工作原理,但是這里介紹了如何在沒有計時器的情況下解決此問題。

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;

就像我說的,我不知道為什么在404嘗試時nextSibling為null,但是如果js網址正確,則nextSibling具有值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM