這個問題長期以來一直一個隨機出現,又十分難以重現和定位。幾經努力之后定位到了,在一個帶有復雜的內嵌iframe的頁面,當內嵌的iframe正在渲染的過程中關閉IE 瀏覽器的時候,會比較容易發生這個問題。
比較容易猜想的是IE在關閉iframe的時候出現了某些問題。猜測是幾個iframe相互有通過top的腳本調用有關系,或者幾個iframe和top都在各自不同的域名下有關系,但是頁面太復雜進一步定位具體是什么問題十分困難(當試圖簡化頁面的時候,問題往往就不能重現了)。而且問題出現在瀏覽器內部,就算具體定位到了不一定就能夠解決。所以更容易和更有意義的,可能是回避“連續彈出新窗口”這個問題。
最開始的想法是,IE既然在出問題的時候是正在渲染iframe,那么此時可能cpu特別繁忙導致了問題,如果可以回避cpu的最高峰期,把渲染iframe的動作做一定的延遲,也許就可以解決問題。試驗后發現,只是減緩了頁面的展現速度,對問題的解決基本沒用幫助。
換個想法,想想如果我們自己做瀏覽器,我們在處理這個問題的時候會怎么做呢,容易出什么問題呢?我們可以做這樣的猜測:IE關閉窗口的時候,是先關閉和回收了最外層的window對象,然后收集它引用的各種資源,一一進行關閉和回收。也就是說,相當于一個隊列式(先打開的window對象先銷毀回收,后打開(被引用)的window對象后銷毀和回收)或者遞歸式(父window對象先銷毀,子window對象后銷毀)的操作:。
看看下面這個測試頁面的關閉順序,其實很耐人尋味(把代碼保存為一個html文件后刷新頁面):
<iframe name="emu1" src="javascript:'<iframe name=emu2></iframe><iframe name=emu3></iframe>'"></iframe>
<iframe name="emu4" src="javascript:'<iframe name=emu5></iframe><iframe name=emu6></iframe>'"></iframe>
<SCRIPT LANGUAGE="JavaScript">
setTimeout(function(){
window.attachEvent('onbeforeunload',function(){alert('parent')})
frames['emu1'].attachEvent('onbeforeunload',function(){alert('iframe1')})
frames['emu1'].frames['emu2'].attachEvent('onbeforeunload',function(){alert('iframe2')})
frames['emu1'].frames['emu3'].attachEvent('onbeforeunload',function(){alert('iframe3')})
frames['emu4'].attachEvent('onbeforeunload',function(){alert('iframe4')})
frames['emu4'].frames['emu5'].attachEvent('onbeforeunload',function(){alert('iframe5')})
frames['emu4'].frames['emu6'].attachEvent('onbeforeunload',function(){alert('iframe6')})
},0)
</SCRIPT>
這樣子很容易帶來的一個問題是,對象的銷毀和資源的回收工作,一般來說是作為低優先級的操作,要為高優先級的操作讓路的,那么在top窗口被銷毀回收的時候,各個iframe的渲染工作,作為優先級比較高的計算,仍在繼續進行。等到各個iframe渲染完成了以后,才發現他本來以為一直在哪里的parent(或者top)句柄,現在指向了一個隨機的位置,于是就發生了不可預測的后果。
假如問題真的是這樣,那么解決方案可能是
1 對關閉操作觸發的銷毀和回收操作,提高優先級別,或者
2 一但觸發關閉操作,立刻主動停止所有的渲染操作,全部資源等待回收,或者
3 對window的關閉操作采用棧式的順序,晚創建的先銷毀,或者或者冒泡式的時序,子窗口先銷毀再銷毀父窗口。
現在我們的問題是瀏覽器自己是不會去調整自己的運算優先級和銷毀順序的,那么我們能否用腳本來幫助它調整一下window對象的銷毀次序呢:
<div id="emu"><iframe src="javascript:'this is an iframe'"></iframe></div>
<SCRIPT LANGUAGE="JavaScript">
window.attachEvent('onbeforeunload',function(){document.getElementById("emu").innerHTML="iframe closed";alert('parent')})
</SCRIPT>
經過這樣的處理后,在可以穩定重現連續打開IE窗口的計算機上,此問題消失,應該說得到了初步解決。
這個問題其實歷史非常悠久了,flashget論壇有人認為是flashget的問題:
http://bbs.flashget.com/post.php?action=reply&fid=14&tid=2461&repquote=16576&extra=
阿里巴巴也蒙受了不白之冤:
http://club.china.alibaba.com/forum/thread/view/_22629427_.html
同樣不幸的還有土豆網,土豆的官方聲明把箭頭指向了BHO,不知是否有根據,實際試驗至少有部分機器確實選中了“啟用第三方瀏覽器擴展”,并且禁止此選項后問題解決了,但是這個操作也很難作為一個解決方案。
http://bbs.tudou.com/topic/20061231/5686
但是網上搜不到其他相關的解決方案,不少人都以為是中了木馬、病毒或者打開的網頁帶有惡意腳本,msdn上一時也搜不到相關的資料。特此貼出來共享 。