JavaScript?定時器關鍵點及使用場景解析
正文
JavaScript 定時器是實現(xiàn)循環(huán)行為甚至觸發(fā)延遲操作的好功能。無論有什么基于時間的邏輯,定時器都可以提供支持。在 JavaScript 中有兩個定時器函數(shù):setTimeout
和 setInterval
。接下來看看有哪些定時器以及它們是如何工作的。
關于計時器的關鍵點
在深入了解定時器的具體細節(jié)之前,有幾個非常關鍵的點需要記住。
并不完全準確
定時器要么在一定秒數(shù)后觸發(fā)一個動作,要么在每次指定的超時結(jié)束時重復一個動作。但是,盡管期望可能是它們精確到秒,但事實并非如此。
這些計時器的規(guī)范聲明它們將使用時間參數(shù)(如指定的秒數(shù))作為最短等待時間。但如果還有其他任務需要先完成,它們肯定會花費更長的時間。
只有當你邏輯依賴于精確的時間測量時,這才會成為問題,比如讓時鐘通過 setInterval
回調(diào)來計算秒數(shù)。
異步函數(shù)
這意味著它們在完成之前不會停止程序流。即使指定 0
作為超時值,它們的行為仍然是異步的。
這意味著這些函數(shù)會將對想要觸發(fā)的函數(shù)的引用添加到事件循環(huán)中,所以即使在超時值上指定了 0
,引用也會在接下來發(fā)生的所有事情之后排隊。
setTimeout
setTimeout
函數(shù)可能是最容易理解的函數(shù),因為主要目標是在幾秒后觸發(fā)一個函數(shù),只會執(zhí)行一次。
這個函數(shù)參數(shù)如下:
- 要執(zhí)行的函數(shù)引用:這是時間一到就會觸發(fā)的代碼邏輯。
- 函數(shù)執(zhí)行前的等待的秒數(shù)
- 然后所有其他參數(shù)以相同的順序傳遞給執(zhí)行的函數(shù)。
下面的代碼將在 3
秒后打印 Hello World
:
setTimeout(console.log, 3000, "Hello", "World");
等效于以下代碼:
setTimeout( (strHello, strWorld) => { console.log(strHello, strWorld); }, 3000, "Hello", "World" );
setTimeout
是一種特殊類型的異步函數(shù),因此無論在其后編寫什么代碼,都將在觸發(fā)該函數(shù)之前執(zhí)行,如下:
console.log("執(zhí)行了第 1 行代碼"); setTimeout(() => { console.log("執(zhí)行了第 3 行代碼"); }, 1000); console.log("執(zhí)行了第 5 行代碼"); console.log("執(zhí)行了第 6 行代碼"); setTimeout(function () { console.log("執(zhí)行了第 8 行代碼"); }, 0); console.log("執(zhí)行了第 10 行代碼");
輸出的結(jié)果如下:
執(zhí)行了第 1 行代碼
執(zhí)行了第 5 行代碼
執(zhí)行了第 6 行代碼
執(zhí)行了第 10 行代碼
執(zhí)行了第 8 行代碼
執(zhí)行了第 3 行代碼
請注意第 3 行和第 8 行是如何最后執(zhí)行的,即使第 8 行的超時為 0
。
在討論 setTimeout
之前,如果設置超時值然后意識到必須停止它會發(fā)生什么?可以定義一個變量保存 setTimeout
的返回值(計時器 ID),則可以使用 clearTimeout
函數(shù)在超時之前停止計時器。
console.log("執(zhí)行了第 1 行代碼"); const timerId = setTimeout(() => { console.log("執(zhí)行了第 3 行代碼"); }, 1000); console.log("執(zhí)行了第 5 行代碼"); clearTimeout(timerId); console.log("執(zhí)行了第 6 行代碼"); setTimeout(function () { console.log("執(zhí)行了第 8 行代碼"); }, 0); console.log("執(zhí)行了第 10 行代碼");
執(zhí)行結(jié)果如下,少了一個定時器的輸出:
執(zhí)行了第 1 行代碼
執(zhí)行了第 5 行代碼
執(zhí)行了第 6 行代碼
執(zhí)行了第 10 行代碼
執(zhí)行了第 8 行代碼
setInterval
setInterval
函數(shù)與 setTimeout
非常相似,但它不是只觸發(fā)一次函數(shù),而是一直觸發(fā)函數(shù)直到停止。
此函數(shù)的簽名與 setInterval
函數(shù)的簽名完全相同,所有參數(shù)的也相同。
const names = ["劉備", "關羽", "張飛", "趙云", "黃忠"]; function sayHi(list) { let name = list[Math.round(Math.random() * 10) % 4]; console.log("你好!", name); } console.log("蜀漢五虎將"); const intervalID = setInterval(sayHi, 1000, names); setTimeout(() => { clearTimeout(intervalID); }, 4000);
上面的代碼將啟動一個每 1
秒觸發(fā)一次的循環(huán),當它觸發(fā)時,將選擇一個隨機名稱并打印字符串 你好! <name>。設置了 4 秒的超時時間,通過調(diào)用 clearTimeout
函數(shù)來結(jié)束無限循環(huán)。當然,也可以使用 clearInterval
函數(shù),但由于它們使用相同的計時器池,可以互換使用它們。
區(qū)別
setTimeout
僅觸發(fā)一次表達式,而 setInterval
在給定的時間間隔后保持定期觸發(fā)表達式(除非手動終止)。
使用場合
除了執(zhí)行定時操作,結(jié)合 Promise
方法,結(jié)合 setTimeout
可以實現(xiàn)休眠功能。
const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; const asyncFoo = async () => { await sleep(2000); console.log(" 等待2秒輸出"); await sleep(1000); console.log(" 等待1秒輸出"); }; console.log("開始執(zhí)行"); asyncFoo();
Promise
結(jié)合 setInterval
可以實現(xiàn)一些數(shù)據(jù)的最大檢測次數(shù),如某個數(shù)據(jù)通過API驗證,驗證結(jié)果無法給出正常結(jié)果,超過一定次數(shù)提示錯誤。
const fakeApiCheck = async () => { console.log("檢查中..."); return Math.random() > 0.8; }; const asyncInterval = async (callback, ms, triesLeft = 5) => { return new Promise((resolve, reject) => { const interval = setInterval(async () => { if (await callback()) { resolve(); clearInterval(interval); } else if (triesLeft <= 1) { reject(); clearInterval(interval); } triesLeft--; }, ms); }); }; const dataCheck = async () => { try { await asyncInterval(fakeApiCheck, 500); } catch (e) { console.log("驗證錯誤"); } console.log("驗證完成!"); }; dataCheck();
總結(jié)
計時器是生成重復或延遲行為的絕佳函數(shù),它們非常有用,尤其是當必須在某些基于時間的條件下與其他服務進行交互時。超時和間隔都可以在使用 clearInterval
或者 clearTimeout
函數(shù)觸發(fā)之前強制停止。
以上就是JavaScript 定時器關鍵點及使用場景解析的詳細內(nèi)容,更多關于JavaScript 定時器的資料請關注腳本之家其它相關文章!
相關文章
微信小程序 后臺https域名綁定和免費的https證書申請詳解
這篇文章主要介紹了微信小程序 后臺https域名綁定和免費的https證書申請詳解的相關資料,需要的朋友可以參考下2016-11-11競態(tài)條件Race condition及如何避免的三種方案詳解
這篇文章主要為大家介紹了競態(tài)條件Race condition及如何避免的三種方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10