關於setTimeout的妙用
定義
在指定的延遲時間之後調用一個函數或執行一個代碼片段
這個是setTimeout最主要的功能,但也是很坑的地方,首先javascript其實是運行在單線程的環境下,意味者定時器會在未來的某個時間支持,但是具體的執行的時間並不能夠很準確的運行,容易受到其它時間的影響,比如DOM的計算、事件的執行、各種函數的執行和運算。但是我們可以利用延遲執行的一些特性來達到我們想要的功能。、
window.setTimeout(callbask, delay, [param1, param2, ...])
函數節流
程序運行過程中對某個函數調用次數很多導致界面不斷回流或者重排,這時候就需要對這個函數進行節流,比如監聽touchmove、scroll事件等,可以限定函數在單位時間內只執行一次
var throttle = function(method, context) { clearTimeout(method.tId); method.tId = setTimeout(function(){ method.call(context); },100); }
控制執行
點擊事件是會產生冒泡,執行的順序是當前點擊元素->父元素->...->document,一直往上執行到document。如果對當前元素的點擊事件處理加上setTimeout的話,那麽執行順序就會改變為父元素->...->document->當前元素。這樣就可以控制冒泡事件的執行順序
var parent = document.getElementById("parent"); var child = document.getElementById("child"); document.body.addEventListener("click", function(e) { console.log("body"); }, false); parent.addEventListener("click", function(e) { console.log("parent"); }, false); child.addEventListener("click", function(e) { setTimeout(function() { console.log("child"); }, 0); }, false); /* *parent *body *child */
構建一個輪詢任務
javacsript中已經有一個開啟輪詢的方法,就是setInterval,但是這種存在一個問題就是執行間隔往往就不是你希望的間隔時間
比如有個輪詢任務間隔是100ms,但是執行方法的時間需要450ms,那麽在200ms、300ms、400ms本來是計劃中執行任務的時間,瀏覽器發現第一個還未執行完,那麽就會放棄2、3、4次的任務執行,並且在500ms之後再次執行任務,這樣的話,其實再次執行的間隔就只有50ms。使用setTimeout構造輪詢能保證每次輪詢的間隔
setTimeout(function(){ alert(1); setTimeout(arguments.callee, 100); },100)
分塊處理耗時計算
瀏覽器給javascript的運行規定了內存和時間,假如javascript運行的時間超過了規定時間,那麽瀏覽器就會‘‘報錯‘‘
for(var i = 0; i < arr.length; i++){ //耗時很久的嵌套循環或者運算 doSomeing(arr[i]); }
假如在循環中做的處理的邏輯不是同步的話,那麽可以把邏輯‘‘分片‘‘執行
sertTimeout(function(){ var item = arr.shift(); dosomeing(item); if(arr.length <0 ){ setTimeout(arguments.callee, 100); } }, 100);
延遲JS引擎的調用
GUI渲染線程和JS引擎的執行之間是互斥,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎執行完畢時立即被執行。這樣的結果會導致新內容很晚才能渲染完成,很多時候我們需要讓界面先渲染完成之後在去調用JS引擎來執行,那麽可以使用setTimeout來延遲JS引擎的調用
var div = document.createElement(‘div‘); div.setAttribute(‘style‘, ‘background-color:#233; width:100px; height:100px‘); document.body.appendChild(div); setTimeout(function() { alert(1); }, 100);
關於setTimeout的妙用