2010年9月25日 星期六

setInterval 與 clearInteval 的問題!?

錯誤的用法:
var timer;
function xxxx(){
   window.ClearInterval(timer)
   timer = window.setInterval("abc()",1000);
}


有一天我發現呼叫clearInterval竟然無法停止之前的setInterval!
原來我把他們寫在同一行,導致了此問題,
以下文章寫到,
"如果在setInterval所調用的那個函數(代號f)中執行clearInterval,該語句執行的效果似乎是被推遲到f函數執行的結束之後"
但實際上我的程式居然無視clearInterval,
因此不但沒有停止之前的循環,還給我"多加一次"的循環!

因此暫時解法如下:

var timer;
var firstrun = 0;
function xxxx(){
  //window.ClearInterval(timer)
  if (firstrun==0){
    timer = window.setInterval("abc()",1000);
    firstrun = 1;
  }
}


什麼!?就不要clearInterval?還用個鬼東西!firstrun?
沒錯,由於同一行既clear又set,所以只好就無視啦!

有其他解法就請待高人了...



以下為參考文章:
來源: 網路
--------------------
setInterval:注意變量的生命期 | 使用外部function的變量作為判斷閾值


setInterval有個有趣的現象。如果在setInterval所調用的那個函數(代號f)中執行clearInterval,該語句執行的效果似乎是被推遲到f函數執行的結束之後,如果是如上例21.,22. 行代碼,clearInterval的執行依賴有關的計數器或閥值變量->如果那個變量(例如t)是f局部的,則系統每次都需要重新生成f的callobject,然後去和該callobject的局部變量相比較,決定是否執行clearInterval;即使達到了不再繼續調用f的條件,由於測試變量在f callobject內部,系統反覆生成f callobject執行clearInterval,下次再重複此動作; 當指令寄存器在執行inner function中的語句,允許inner function的指令去刪除系統對那個調用inner function的外部過程或函數的引用嗎?(暫理解為timer引用著系統在主線程中不斷調用inner f的那個定時器過程,clearInterval timer的內容之一是刪除timer對那個過程的引用),或許這裡面因為循環引用或者是其他特殊的機制,至少在inner function的內部是不能執行的;因此當22語句的條件得以實行且是clearInterval這個特殊的情況,系統內部會做出特殊的標記,要在inner f執行完後執行清除定時器必要的工作。給我的感覺是,js process的中間代碼把上例中21., 22.行代碼優化成了同一個執行單元的中間代碼語句。並且當系統在執行inner f中的22句,系統重新獲得需要執行它的那些變量引用等等,不幸的是,這導致f的callobject重新被生成,而f內部的變量t每次都讀取外部的值,t早就超過了閾值,導致timer cleared對話框會不斷的被提示。
例子中,nested function的outer function中定義t,判斷t可得到正確的行為,判斷2.1處的e.style.opacity也可以得到正確行為,因為e是在outer function中,並且依賴於js process 默認string to number的轉換成整數的行為,前9次都是0,第10次>=閥值,行為正確;但是使用在f內部聲明的t,或者2.2處,使用parseInt(e.style.opacity)都得不到正確的行為,特別是2.2處,parseInt(e.style.opacity)表達式生成一個f內部的匿名的變量,使用之後被js process丟棄該在f callobject中生成的匿名臨時變量和f callobject一樣準備GC,因此2.2處在if語句中使用parseInt來判斷表達式也得不到正確的行為。這點setIntveral的特殊性需留意。
例子使用在outer function定義閥值var t的方法,每次通過parseInt來設置t,比2.1處,e雖然是外部變量但依賴默認的data type casting,2.1晦澀,且容易忽略setInterval的機制

0 留言:

張貼留言