消除IE stop running this script彈出框

問題描述和分析:

IE跳出了stop running this script的提示, 提示如下:

Stop runningthis script?

A script on thispage is causing your web browser to run slowly. If it continues to run, yourcomputer might become unresponsive.

 

當然有些提示可能如下:

A script on thispage is causing Internet Explorer to run slowly. If it continues to run, yourcomputer may become unresponsive. Do you want to abort the script?

你可以點擊"YES"或"NO",點擊"NO",IE會繼續執行腳本,執行結果跟沒有彈出這個框的結果是一樣的,點擊"YES",IE停止執行腳本,這時候看到狀態肯定是不正常的,如果用戶都理解原理,並且每次都選擇"NO",那麼我們就不需要做任何修改了. 但這肯定是不可能的.

咋一看時, 以爲肯定是程序的性能慢得IE自己都受不了了,所以跳個框出來,希望用戶手動停止, 我的第一反映當然也是這樣. 但是奇怪的是我在一臺運行速度很快的電腦上, 2秒左右IE也跳出了這個信息, 這就讓我困惑不已了,雖然2秒不算短,但是基於web技術的程序代碼執行時間超過2秒的應該是可以接受的, 於是google了一下, 看到IE support team 提出的一個解決方案, 參考鏈接爲:http://support.microsoft.com/kb/175500

裏面明確解析如下:

As of InternetExplorer 4.0 and later versions, the time-out is no longer a fixed value basedon Windows messages. Internet Explorer now tracks the total number of executedscript statements and resets the value each time that a new script execution isstarted, such as from a timeout or from an event handler, for the current pagewith the script engine. Internet Explorer displays a "long-runningscript" dialog box when that value is over a threshold amount. Internet Explorerdoesn’t check on each instruction to see if it is over the limit. Periodicallythe script engine polls Internet Explorer with the number of statementsexecuted and Internet Explorer checks if that is over the limit. Because ofthis mechanism, it is possible to execute more than the default limit withoutthe dialog if the entire script execution finishes before the script enginepolls Internet Explorer. 

大致意思是: 從IE4.0的版本開始, 這個'long-running script'的彈出框其實並不是由於你的代碼執行的時間超過了一個預先設定的值,而是週期性的檢查IE執行的代碼總行數是否超過了一個預設的值(這個值可以通過註冊表修改),如果超過了就會彈出上面所說的框. 

這個設計相當有意思,意味着就算你的代碼在1秒鐘內執行完成了,但是如果這1秒鐘之類執行過的語句行數超過了這個預設的固定值,IE還是會彈出這個stoprunning script的框,這顯然會讓我們很困惑. 因爲速度這麼快,還跳出了這個框,難道要我們的代碼不耗時間?

 說實話,我看完這段解釋後,還是不願意接受這個觀點, 只好自己實驗一把了.

 實驗一,本實驗代碼會跳出stoprunning this script框,代碼如下:

</pre><pre name="code" class="html"><html>  
    <head>  
        <title>IE Long Running Script Issue</title>  
    </head>  
    <body>  
        Statements Execution Number: <span id='outputTxt'>0</span>    
        <script type='text/javascript'>         
            function exceedExectutionStatmentsLimit(){  
                var i=0, str='', output=document.getElementById('outputTxt');  
                for(; i<5000000; i++){  
                    strstr=str+i;  
                    if(i % 100000 ===0){  
                        output.innerHTML=i;  
                    }  
                }  
                output.innerHTML=i;  
            }             
            exceedExectutionStatmentsLimit();  
        </script>  
    </body>  
</html>  

用IE打開上面的html頁面,會跳出stop...的框,選擇yes後,頁面輸出爲

StatementsExecution Number: 1700000

這裏暫時不解釋這個輸出,下面會有解釋

 

實驗二,本實驗IE不會跳出stop running this script框,雖然本代碼的執行時間超過了上面的代碼

<html> 
    <head> 
        <title>IE Long Running ScriptIssue</title> 
    </head> 
    <body> 
        Statements Execution Number: <spanid='outputTxt'>0</span> 
        <scripttype='text/javascript'> 
            functionAvoidLongRunningScriptMessageDisplay(){ 
                var i=0, str='',output=document.getElementById('outputTxt'); 
                 
                (function () { 
                    for (; i < 9000000; i++){ 
                                str+=i; 
                        // Every 100,000iterations, take a break 
                        if (i % 100000 == 0){ 
                               output.innerHTML=i; 
                            // Manuallyincrement `i` because we break 
                            i++; 
                            // Set a timer forthe next iteration  
                            window.setTimeout(arguments.callee); 
                            break; 
                        } 
                    } 
                })();                
            } 
           AvoidLongRunningScriptMessageDisplay(); 
        </script> 
    </body> 
</html> 

 頁面輸出爲Statements Execution Number: 8900000


所以至少得出一個結論,IE官方的解釋的確是言行一致,彈出框的跳出只與執行過的代碼總行數有關,與其執行耗費的時間無關.

 

那麼接下來有兩個問題:

1)代碼執行行數的限制是多;

代碼執行行數的限制是多少, 這個值是在註冊表裏面可修改的,默認是500萬行, 當然你可以修改成更大,這樣你也能阻止IE跳出stop running this script框,但顯然

你只能解決你的IE,其他人的電腦註冊表沒修改過的話,還是會跳出來的,所以這個方案並不好.關於如何修改本文開頭的解決方案3)已經給出了答案.

 

另外需要注意的是,事實上IE不會每執行一條語句就會檢查是否總共執行過的代碼行數是否超出了限制,這樣顯然很耗性能也不明智,IE會週期性的去檢查,所以如果你

碰巧在IE來檢查時沒有超過限制,而不檢查時超過了限制,你也不會看到stop script彈出框,當然這就跟中獎一樣,看你運氣了.

 

2)代碼執行的總行數是怎麼計算的;

a) 使用setTimeout調用的函數, 函數裏面的代碼使用的是一個新的計數器

b) 事件處理函數理的代碼使用的也是一個新的計算器

c) 除此之外使用的是同一個計數器,很顯然,如果你的代碼既沒有setTimeout也沒有是用

    event handler,那麼很容易讓計數器超過閥值

 

另外實驗一中點了yes後,爲什麼輸出的是Statements Execution Number: 1700000, 而不是500萬呢,那是因爲for循環了還有其他的代碼,輸出的是170萬,

但是實際執行的已經有500萬了.

 

如果你還是不相信上面的結論,那麼可以用簡單的方式,用程序生成500萬行左右的javascript語句,看看是否真是500萬行會跳出框,我給出了java代碼的實現,

 

有興趣你可以試一下,但提前預告一些,如果你生成了500萬行語句,整個html文件大概有80M大,請做好心理準備,只怕目前你還沒有運行過如此大的網頁,你的IE

很容易死掉,電腦也可能會變慢,另外下面代碼使用的是jdk1.7,

importjava.io.IOException; 
importjava.nio.charset.Charset; 
importjava.nio.file.Files; 
importjava.nio.file.Path; 
importjava.nio.file.Paths; 
importjava.util.ArrayList; 
importjava.util.List; 
public classGenerateJavascriptCodeForTesting { 
 
    public static void main(String[] args){ 
        PathoutPut=Paths.get("c:\\tmp\\jsTest.html"); 
        List<String> content = newArrayList<String>(); 
       content.add("<html><head><title>IE Long RunningScript Issue</title></head><body><spanid='outputTxt'>0</span><scripttype='text/javascript'>"); 
        content.add("functionexceedExectutionStatmentsLimit(){var i=0, str='',output=document.getElementById('outputTxt');"); 
        int i=0; 
        for(;i<6000000;i++){//try 4000000,5000000, 6000000 and see whether the stop running script message will be shownup 
           content.add("str+="+i+";"); 
            if(i%100000==0){ 
               content.add("output.innerHTML="+i+";"); 
            } 
        } 
       content.add("output.innerHTML="+i+";}"); 
       content.add("exceedExectutionStatmentsLimit();"); 
       content.add("</script></body></html>"); 
        try { 
            Files.write(outPut, content,Charset.forName("UTF-8")); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
} 

  

解決方案:

 

首先特別提出一點, 觸發事件並執行事件處理函數是一個同步過程,不是異步過程. 可以參考我的另一篇文章:http://darrenzhu.iteye.com/blog/2029822

 

1. setTimeout

使用setTimeout將大量代碼分開執行,每個setTimeout會使用一個新的代碼行數計數器,這樣你的代碼就會減少彈出"Stop running script ..."窗口的機會. 當然很多時候,我們並不會碰到該問題,畢竟500萬行代碼不是個小數目,不過程序命中的概率比你中500萬的彩票顯然要容易得多.

 

2. 通過事件

把你的代碼放到事件處理函數裏面, 當然事件可以是系統的事件如mouseover,click, 也可以是你自定義和手動觸發的. 事件機制爲什麼能解決這個問題,是因爲IE的代碼計數器對事件處理函數裏面的代碼重新計數,已經跟當前控制流的代碼計數器分開了.

 

我更傾向於用事件機制來解決, 因爲用setTimeout,你必須指定一個時間,時間設置得不管有多麼短,都會有延遲,而事件不會有延遲,當你觸發了事件,立馬會去執行事件處理函數.

 

3. 修改註冊表, 至於爲什麼可以通過修改註冊表解決這個問題,請看下文的解釋

要修改IE4 - IE8的time-out的值,按如下方式操作:

1)運行Regedit32.exe, 找到下面這一項

HKEY_CURRENT_USER\Software\Microsoft\InternetExplorer\Styles

如果Styles這一項不存在, 你可以創建這一個項

 

2)創建一個類型爲DWORD的鍵值"MaxScriptStatements", 並且設置它的值爲你需要的腳本代碼總函數, 如果你不知道設置多少合適, 你可以將其設置成0xFFFFFFFF, 這樣就可以避免IE彈出"Stop running Script ..."的框.

 

默認Styles這一項是不存在的, 這個時候默認的彈出time-out框的代碼總函數限制是500萬行, 當然是針對IE4 - IE8來說.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章