setTimeout,setInterval的使用小結


setTimeout

眾所周知setTimeout(fn,time)是等待一段時間后,執行函數fn。
在這個等待是異步的,也就是他不會站着茅坑,當前JS隊列中的其他任務會按序執行
但這里有個問題就是time毫秒過后的fn執行問題。是立即執行?不一定。
這就像是一個買票的隊伍,有正在買票的,有排在后面等待買票的。而setTimeout就相當於剛排到fn買票的時候他突然發現錢包一時翻不出來。
所以他就讓后面的人先買。過了time時間找到錢包后,如果現在沒人買票的話,他可以立即買票。否則他就只能去排隊了(當所有隊列中的內容執行結束后才執行)。

<input type="text" id="io" />
<div id="test" style="width:200px;height:400px;overflow:scroll;"></div>
<script>
//這個函數的執行時間在IE下肯定是大於100ms的
function lost() {
    var test = document.getElementById("test");
    var t1 = new Date();
    var html = [];
    for (var i = 0; i < 10000; i++) {
        html.push('<span>look at here</span>');
    }
    test.innerHTML = html.join("");
    var t2 = new Date();
    //return (t2 - t1) / 1000;糾正
    return t2 - t1;
}
var io = document.getElementById("io"); io.value += "A"; setTimeout(function() { io.value += "B"; }, 100); lost(); io.value += "C"; lost(); io.value += "D"; </script>

最后io的value為ACDB,也證明了不是100ms后立即執行,而是排到了隊伍后面。

也有人見過setTimeout(fn,0);如果上面的內容理解了的話,這個也就不難了:如果沒有隊伍則立即執行,否則就排隊去。


setInterval

setInterval(fn,time)就是一個重復的定時器。
每隔time時間,將fn推入隊列(如果進程空閑則立刻執行),不管是否有fn正在執行或等待隊列。
但是,如果當前隊列中有正在等待的fn,則本次不會向隊列中添加fn。如下

<input type="text" id="io" />
<input type="button" id="insert" value="INSERT" />
<input type="button" id="get" value="GET" />
<div id="test" style="width:200px;height:400px;overflow:scroll;"></div>
<script>
    var io = document.getElementById("io");
    var i = setInterval(function() {
        io.value += "B";
    }, 10);
    
    lost();
    lost();
    setTimeout(function() {
        clearInterval(i);
    }, 10);
    
    //IE下執行時間肯定會是10的好多倍的
    function lost() {
        var test = document.getElementById("test");
        var t1 = new Date();
        var html = [];
        for (var i = 0; i < 10000; i++) {
            html.push('<span>look at here</span>');
        }
        test.innerHTML = html.join("");
        var t2 = new Date();
        io.value += "C";
    }
</script>

結果是CCB
執行lost函數的時間是定時器的很多倍。但在這么長的時間里,定時器只向隊列中推入fn一次。
這個原因也導致了以下兩種不理想情況的出現。

①fn執行時間小於time的時候,經常會間隔時間不一致。

②fn執行時間大於time時,則造成沒有了間隔時間(實際當中會有那么一點點的間隔)

因為這些問題,setInterval就失去了定時器的意義。

所以我們都用循環調用setTimeout來代替setInterval。原理如下

setInterval(fn,time)
//↓↓↓↓↓↓↓↓↓↓↓↓
setTimeout(function(){
    fn();
    setTimeout(arguments.callee,time);
},time);

這樣就可以讓每個fn之間都會至少保持time的間隔。 

注:setTimeout和setInterval的函數環境總是Window。


 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM