setTimeout和setInterval基本用法:javascript
使用setInterVal:java
function doStuff(){
// 此處爲須要執行一段時間T的代碼
}
setInterVal(doStuff, 100);
複製代碼
下來看如何使用setTimeout模擬setInterval:git
function tick() {
doStuff();
setTimeout(tick, 100);
}
tick();
複製代碼
看下正常狀況下二者的區別:github
setInterval每一個定時器之間的間隔是100ms,而setTimeout每隔100ms執行一次doStuff,因此每一個定時器之間的間隔是100 + T(doStuff執行時間爲T);這個T就是本文的關鍵了。web
先看下圖:瀏覽器
在0ms時,定時器1開始進入宏任務隊列;100ms時,定時器1開始執行doStuff1,隊列爲空,定時器2進入隊列;200ms時,由於定時器2還在隊列中,因此定時器3被跳過。瀏覽器不會同時建立兩個相同的間隔計時器。 300ms時,定時器2已經開始執行,隊列爲空,定時器4進入隊列。以此類推~服務器
下面咱們用代碼驗證下。T設置爲140ms。 咱們讓定時器運行5次,按照上述理解,總運行時間應該是:100+5*140 = 800ms。 代碼以下:異步
let i = 0;
console.time("總時間");
function doStuff() {
console.log("delay");
dead(140);
console.timeEnd("測試");
}
function dead(delay) {
var start = new Date().getTime();
while (new Date().getTime() < start + delay);
}
let timer = setInterval(() => {
i++;
if (i > 4) {
clearInterval(timer);
setTimeout(() => {
console.timeEnd("總時間");
}, 0);
}
console.log("interval start");
console.time("測試");
doStuff();
}, 100);
複製代碼
運行結果:函數
能夠看出定時器運行了5次,總時間的確爲800ms。 若是doStuff中的代碼是異步的呢?好比像咱們經常使用的請求接口。 簡單起了個本地服務器,140ms返回結果。代碼很簡單就不上了。下面是js代碼:post
let i = 0;
console.time("總時間");
function delay() {
fetchData();
}
function fetchData() {
return fetch("/home", {
method: "POST"
})
.then(res => {
console.log("res>>>>>>");
})
}
let timer = setInterval(() => {
i++;
if (i > 4) {
clearInterval(timer);
setTimeout(() => {
console.timeEnd("總時間");
}, 0);
}
delay();
}, 100);
複製代碼
控制檯輸出:
能夠看出總時間是500ms,請求接口的異步代碼並不會阻塞定時器。這個也很好理解,定時器中的同步代碼會直接進入隊列,異步代碼註冊事件,完成後進入隊列;因此當異步代碼註冊事件後,這個定時器就執行完了,並非等異步代碼回來後這個定時器纔算結束,否則5次定時器的總時間就是800ms了。結論:
參考文章: