最近寫一些JS動畫,常用到JS中的定時器(setTimeout & set Interval),查找相關資料,有些心得與大家一起分享。
使用setTimeout & set Interval創建的定時器可以實現有趣且有用的功能,初學者可能對Javascript的定時器有誤解,認為它們是線程,其實Javascript是運行於單線程中的,而定時器僅僅是計划在未來的某個時間執行,而具體的執行時間是不能保證的,因為在頁面的生命周期中,不同的時間可能有其它代碼在控制Javascript的里進程。瀏覽器只是負責進行排序,指派某個代碼在某個時間點運行。
下面說下Javascript線程,下圖表示javascript進程時間線。
除了javascript執行進程外,還有一個需要在進程下一次空閑時間執行的代碼隊列,隨着頁面在其生命周期內的推移,代碼會按照執行順序添加到對列中,例如:當一個按鈕被按下時,它的事件處理就會添加到隊列中,並在下一個可能的時間內執行。
定時器對隊列的工作方式是,當特定的時間過去后,將代碼插入,注意添加到隊列並不意味着它會馬上執行,而只能說它會盡快執行,設定一個250ms后執行的定時器,不代表250ms后它會馬上執行,它只會表示在150ms后被加入到隊列中,如果這個時間點隊列是空閑的,那么這段代碼就會被執行。
請看以下代碼:
var btn = document.getElementById("mybtn"); btn.onclick = function () { setTimeout(function () { document.getElementById("message").nodeName = "mymessage"; //其它代碼 }, 250); }
對於定時器最要注意的是:指定的時間間隔表示何時將定時器的代碼添加到隊列中,而不是何時執行代碼。關於這個onclick事伯處理的進程時間線請看下圖:
<script type="text/javascript"> var c = 0 var t function timedCount() { document.getElementById('txt').value = c c = c + 1 t = setTimeout("timedCount()", 1000) } function stopCount() { clearTimeout(t) } </script> <input type="button" value="開始計時!" onClick="timedCount()"> <input type="text" id="txt"> <input type="button" value="停止計時!" onClick="stopCount()">
setInterval() 方法可按照指定的周期(以毫秒計)來調用函數或計算表達式。
setInterval() 方法會不停地調用函數,直到 clearInterval() 被調用或窗口被關閉。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的參數。
關於重復定時器,我們既可以使用setTimeout來重復創建就時器,也可以直接用setInterval,使用setInterval創建的定時器確保了定時器規則地插入隊列中,這個方式問題在於代碼可能在再次添加到隊列之前還沒有完成執行,可能尋到定時器重復運行好幾次,而中間沒有停頓,然而現在的javascript引擎很聰明,能避免這個問題,當使用setInterval時,僅當沒有定時器的任何其它代碼時,才將定時器代碼添加到隊列中,這樣會確保定時器代碼加入到隊列的時間的間隔是為指定的間隔,請注意這只是加入隊列的時間間隔,並不是執行代碼的時間間隔,所以使用setInterval還是會存在兩個問題:(1)某些間隔會被跳過了(2)多個定時器的代碼執行間隔可能會比預期的要小。
為避免這些問題,可以使用如下模式使用鏈式setTimeout調用:
setTimeout(function () { //處理中 setTimeout(arguments.callee, interval); }, interval)
在上面的計時DEMO中也是使用此模式來做循環的。