比較容易猜想的是IE在關(guān)閉iframe的時(shí)候出現(xiàn)了某些問(wèn)題。猜測(cè)是幾個(gè)iframe相互有通過(guò)top的腳本調(diào)用有關(guān)系,或者幾個(gè)iframe和top都在各自不同的域名下有關(guān)系,但是頁(yè)面太復(fù)雜進(jìn)一步定位具體是什么問(wèn)題十分困難(當(dāng)試圖簡(jiǎn)化頁(yè)面的時(shí)候,問(wèn)題往往就不能重現(xiàn)了)。而且問(wèn)題出現(xiàn)在瀏覽器內(nèi)部,就算具體定位到了不一定就能夠解決。所以更容易和更有意義的,可能是回避“連續(xù)彈出新窗口”這個(gè)問(wèn)題。
最開始的想法是,IE既然在出問(wèn)題的時(shí)候是正在渲染iframe,那么此時(shí)可能cpu特別繁忙導(dǎo)致了問(wèn)題,如果可以回避cpu的最高峰期,把渲染iframe的動(dòng)作做一定的延遲,也許就可以解決問(wèn)題。試驗(yàn)后發(fā)現(xiàn),只是減緩了頁(yè)面的展現(xiàn)速度,對(duì)問(wèn)題的解決基本沒(méi)用幫助。
換個(gè)想法,想想如果我們自己做瀏覽器,我們?cè)谔幚磉@個(gè)問(wèn)題的時(shí)候會(huì)怎么做呢,容易出什么問(wèn)題呢?我們可以做這樣的猜測(cè):IE關(guān)閉窗口的時(shí)候,是先關(guān)閉和回收了最外層的window對(duì)象,然后收集它引用的各種資源,一一進(jìn)行關(guān)閉和回收。也就是說(shuō),相當(dāng)于一個(gè)隊(duì)列式(先打開的window對(duì)象先銷毀回收,后打開(被引用)的window對(duì)象后銷毀和回收)或者遞歸式(父window對(duì)象先銷毀,子window對(duì)象后銷毀)的操作:。
看看下面這個(gè)測(cè)試頁(yè)面的關(guān)閉順序,其實(shí)很耐人尋味(把代碼保存為一個(gè)html文件后刷新頁(yè)面):
<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>
這樣子很容易帶來(lái)的一個(gè)問(wèn)題是,對(duì)象的銷毀和資源的回收工作,一般來(lái)說(shuō)是作為低優(yōu)先級(jí)的操作,要為高優(yōu)先級(jí)的操作讓路的,那么在top窗口被銷毀回收的時(shí)候,各個(gè)iframe的渲染工作,作為優(yōu)先級(jí)比較高的計(jì)算,仍在繼續(xù)進(jìn)行。等到各個(gè)iframe渲染完成了以后,才發(fā)現(xiàn)他本來(lái)以為一直在哪里的parent(或者top)句柄,現(xiàn)在指向了一個(gè)隨機(jī)的位置,于是就發(fā)生了不可預(yù)測(cè)的后果。
假如問(wèn)題真的是這樣,那么解決方案可能是
1 對(duì)關(guān)閉操作觸發(fā)的銷毀和回收操作,提高優(yōu)先級(jí)別,或者
2 一但觸發(fā)關(guān)閉操作,立刻主動(dòng)停止所有的渲染操作,全部資源等待回收,或者
3 對(duì)window的關(guān)閉操作采用棧式的順序,晚創(chuàng)建的先銷毀,或者或者冒泡式的時(shí)序,子窗口先銷毀再銷毀父窗口。
現(xiàn)在我們的問(wèn)題是瀏覽器自己是不會(huì)去調(diào)整自己的運(yùn)算優(yōu)先級(jí)和銷毀順序的,那么我們能否用腳本來(lái)幫助它調(diào)整一下window對(duì)象的銷毀次序呢:
<SCRIPT LANGUAGE="JavaScript">
window.attachEvent('onbeforeunload',function(){document.getElementById("emu").innerHTML="iframe closed";alert('parent')})
</SCRIPT>
經(jīng)過(guò)這樣的處理后,在可以穩(wěn)定重現(xiàn)連續(xù)打開IE窗口的計(jì)算機(jī)上,此問(wèn)題消失,應(yīng)該說(shuō)得到了初步解決。
這個(gè)問(wèn)題其實(shí)歷史非常悠久了,flashget論壇有人認(rèn)為是flashget的問(wèn)題:
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
同樣不幸的還有土豆網(wǎng),土豆的官方聲明把箭頭指向了BHO,不知是否有根據(jù),實(shí)際試驗(yàn)至少有部分機(jī)器確實(shí)選中了“啟用第三方瀏覽器擴(kuò)展”,并且禁止此選項(xiàng)后問(wèn)題解決了,但是這個(gè)操作也很難作為一個(gè)解決方案。
http://bbs.tudou.com/topic/20061231/5686
但是網(wǎng)上搜不到其他相關(guān)的解決方案,不少人都以為是中了木馬、病毒或者打開的網(wǎng)頁(yè)帶有惡意腳本,msdn上一時(shí)也搜不到相關(guān)的資料。特此貼出來(lái)共享 。