JavaScript定時(shí)器setTimeout、setInterval使用詳解
定時(shí)器:按我個(gè)人理解來說就是固定某個(gè)時(shí)間后,時(shí)間到了,就提醒我時(shí)間到了。
程序中的定時(shí)器:相當(dāng)于倒計(jì)時(shí),也相當(dāng)于計(jì)時(shí)器。作用是在設(shè)定的某個(gè)時(shí)間后,執(zhí)行特定的方法。
我們先來了解一下setTimeout定時(shí)器,他的特點(diǎn)就是只能用一次,也稱為一次性定時(shí)器。
setTimeout( func, time, argument1, argument2, .... );
語法解析:
1、func:固定時(shí)間后執(zhí)行的方法
2、time:設(shè)置固定的時(shí)間-按毫秒計(jì)算
3、argument:傳入方法的參數(shù)
案例:?? ?setTimeout(function(name,gender){ ?? ??? ?console.log(name + " is " + gender); ?? ?}, 1000, "Tom", "boy");簡(jiǎn)寫:
?? ?setTimeout((name,gender) => { ?? ??? ?console.log(name + " is " + gender); ?? ?}, 1000, "Tom", "boy");案例解析:
開啟了一個(gè)一次性定時(shí)器,1秒后執(zhí)行我給定的函數(shù)。
接著看看 setInterval定時(shí)器,他的特點(diǎn)就是可以重復(fù)執(zhí)行給定的函數(shù)。
console.log("1 ===>"); setTimeout(function(name,gender){ console.log(name + " is " + gender); }, 1000, "Tom", "boy"); console.log("2 ===>"); 執(zhí)行結(jié)果: > "1 ===>" > "2 ===>" > "Tom is boy"
接下來就開始圈重點(diǎn)了:
定時(shí)器概念了解了,也會(huì)造定時(shí)器了,那這個(gè)定時(shí)器什么時(shí)候調(diào)用呢,因?yàn)槲覀兊?javaScript代碼是從上到下,逐行執(zhí)行,那到了定時(shí)器這行我們的進(jìn)程會(huì)不會(huì)等定時(shí)器執(zhí)行完了再執(zhí)行定時(shí)器后面的代碼呢?答案是不會(huì)等!
遇到定時(shí)器,會(huì)將定時(shí)器加入到任務(wù)隊(duì)列中(宏任務(wù)),等所有代碼執(zhí)行完了,程序會(huì)看一下隊(duì)列中還有什么沒有完成的 ,如果有沒完成的,就執(zhí)行一下。
這樣說可能有點(diǎn)抽象,看下案例好了。
console.log("1 ===>"); setTimeout(function(name,gender){ console.log(name + " is " + gender); }, 1000, "Tom", "boy"); console.log("2 ===>"); 執(zhí)行結(jié)果: > "1 ===>" > "2 ===>" > "Tom is boy"
注意:任務(wù)隊(duì)列里的執(zhí)行順序是按先來后到的
接下來再深入理解一下,我們先思考一個(gè)問題,一次性定時(shí)器和重復(fù)性定時(shí)器區(qū)別在哪,不可能就只是調(diào)一次和調(diào)多次這么簡(jiǎn)單吧。
提醒:接下來的內(nèi)容比較重要,有點(diǎn)抽象但需要理解透徹
案例:假設(shè)我們需要每隔一秒控制臺(tái)輸出一句話。
結(jié)合我們本文的學(xué)習(xí),給出思路:
1、一次性定時(shí)器的函數(shù)里再調(diào)定時(shí)器,形成循環(huán)。
2、開啟一個(gè)重復(fù)性定時(shí)器
編寫實(shí)現(xiàn)代碼:
思路1: setTimeout(function run(name,gender){ console.log(" hello"); setTimeout(run,1000); }, 1000); 思路2: setInterval(()=>{ console.log("hello") },1000);
看到這大家可能會(huì)不禁感嘆,就這?就這?這哪復(fù)雜了,逗我呢。
那不妨思考一下,第二個(gè)一次性定時(shí)器啥時(shí)候開始執(zhí)行呢?第三個(gè)呢?第n個(gè)呢?程序運(yùn)行的第n秒?
那我稍微改造一下剛剛的案例好了
let start = Date.now(); // 程序一運(yùn)行的時(shí)間 let times = []; // 用來記錄運(yùn)行時(shí)間的數(shù)組 let sTime = setInterval(()=>{ times.push(Date.now() - start); // 記錄下執(zhí)行時(shí)間 if (start + 5000 < Date.now()) { console.log(times); } },1000);
接著可以思考一下輸出的結(jié)果是什么。
然后再來思考重復(fù)性定時(shí)器,第二次函數(shù)調(diào)用是啥時(shí)候執(zhí)行呢?第三個(gè)呢?第n個(gè)呢?
再稍微改造一下好了
let start = Date.now(); // 程序一運(yùn)行的時(shí)間 let times = []; // 用來記錄運(yùn)行時(shí)間的數(shù)組 let sTime = setInterval(()=>{ times.push(Date.now() - start); // 記錄下執(zhí)行時(shí)間 if (start + 5000 < Date.now()) { console.log(times); } },1000);
好了,留些時(shí)間思考一下…
思考好了嗎,好了的話一起揭曉一下答案吧。
第一種情況:
> "1 ===>"
> "2 ===>"
> "1 ===>"
> "2 ===>"第二種情況:
> Array [1001, 2003, 3003, 4000, 5000, 6000]分析:
情況1:思考這個(gè)問題就可 -> 輸出 "1 ===>" 之后我開啟了另一個(gè)定時(shí)器,此時(shí)是不是應(yīng)該再輸出"1 ===>"?然后就進(jìn)入了定時(shí)器循環(huán),結(jié)果一直只有"1 ===>"?
結(jié)合我們的結(jié)果,可以發(fā)現(xiàn)下一個(gè)定時(shí)器是什么時(shí)候開的?沒錯(cuò),執(zhí)行完第一個(gè)定時(shí)器函數(shù)內(nèi)的代碼后再執(zhí)行的。
情況2:根據(jù)時(shí)間的間隔很容易知道時(shí)間就是1秒上下幾毫秒,所以下一個(gè)定時(shí)器是第一個(gè)定時(shí)器時(shí)間結(jié)束后立即開啟的。
這就是他們兩個(gè)比較靠底層的區(qū)別。
總結(jié)的話就留給大家自己總結(jié)吧,畢竟一千個(gè)讀者就會(huì)有一千個(gè)讀者(哈哈,開個(gè)玩笑,說句可能像話的話??)。
現(xiàn)在我們已經(jīng)大致了解了定時(shí)器以及觸發(fā)時(shí)間,那么會(huì)造定時(shí)器了不會(huì)取消就有點(diǎn)說不過去了,下面一起看看怎么取消定時(shí)器。
let timerId1 = setTimeout(...); clearTimeout(timerId1); // 取消一次性定時(shí)器,timeId1 是唯一且必傳參數(shù) let timerId2 = setInterval(...); clearInterval(timerId2)。 // 取消重復(fù)定時(shí)器,timeId2 是唯一且必傳參數(shù)
注意:定時(shí)器開啟了一定要關(guān)閉,要做到有始有終,不然會(huì)一直消耗內(nèi)存,到時(shí)候就就很容易程序崩潰。
還有一個(gè)留最后講的,因?yàn)楸容^細(xì)節(jié)。
下面我們來看個(gè)案例
let start = Date.now(); let times = []; setTimeout(function run() { times.push(Date.now() - start); // 保存前一個(gè)調(diào)用的延時(shí) if (start + 50 < Date.now()) console.log(times); // 100 毫秒之后,顯示延時(shí)信息 else setTimeout(run); // 否則重新調(diào)度 }); 結(jié)果: > Array [1, 2, 4, 5, 9, 13, 18, 22, 27, 32, 36, 42, 46, 50, 55]
let start = Date.now(); // 程序一運(yùn)行的時(shí)間 let times = []; // 用來記錄運(yùn)行時(shí)間的數(shù)組 let sTime = setInterval(()=>{ times.push(Date.now() - start); // 記錄下執(zhí)行時(shí)間 if (start + 50 < Date.now()) { console.log(times); clearInterval(sTime); // 清除定時(shí)器 } }); 結(jié)果: > Array [1, 2, 3, 4, 8, 13, 16, 20, 25, 28, 32, 36, 40, 44, 48, 53]
感興趣的同學(xué)可以分別思考一下這兩組數(shù)組的規(guī)律,然后再往下看
好了,這就不賣關(guān)子了,直接把結(jié)論告訴大家吧
瀏覽器會(huì)將 setTimeout 或 setInterval 的五層或更多層嵌套調(diào)用(調(diào)用五次之后)的最小延時(shí)限制在 4ms。這是歷史遺留問題。
最后,大家拷貝案例執(zhí)行的時(shí)候,運(yùn)行的結(jié)果很大概率和我這個(gè)結(jié)果不一樣,影響的因素有瀏覽器版本、類型等等問題。不過這也不影響結(jié)論是正確的
總結(jié)
到此這篇關(guān)于JavaScript定時(shí)器setTimeout、setInterval使用的文章就介紹到這了,更多相關(guān)定時(shí)器setTimeout、setInterval使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javscript刪除數(shù)組中指定元素并返回新數(shù)組
把數(shù)組中某個(gè)值刪除,并返回新數(shù)組,需要遍歷舊數(shù)組找到要?jiǎng)h除的元素,下面有個(gè)不錯(cuò)的示例,大家可以參考下2014-03-03JavaScript中this的9種應(yīng)用場(chǎng)景及三種復(fù)合應(yīng)用場(chǎng)景
本文通過9中應(yīng)用場(chǎng)景給大家分析this關(guān)鍵字的用法,需要了解的朋友可以參考下本文2015-09-09toString()一個(gè)會(huì)自動(dòng)調(diào)用的方法
toString方法的作用是不用多說的了,這個(gè)JavaScript內(nèi)置方法還有一個(gè)特性是:在執(zhí)行一些特殊方法的時(shí)候,比如alert或innerHTML等方法,它將由腳本解析器自動(dòng)調(diào)用。2010-02-02js監(jiān)控IE火狐瀏覽器關(guān)閉、刷新、回退、前進(jìn)事件
本節(jié)主要介紹了js監(jiān)控IE火狐瀏覽器關(guān)閉、刷新、回退、前進(jìn)事件的方法2014-07-07JS解決?Array.fill()參數(shù)為對(duì)象指向同一個(gè)引用地址的問題
這篇文章主要介紹了JS解決?Array.fill()參數(shù)為對(duì)象指向同一個(gè)引用地址問題,解決方案使用map返回出不同的引用的地址,fill參數(shù)可隨意填寫(不為空),主要是map函數(shù)中返回的數(shù)據(jù),需要的朋友可以參考下2023-02-02