極度重要之定時器

說到定時器,大家就肯定知道setTimeout()和setImterval(),但是他們背后還有很多更重要的知識點需要我們?nèi)フ莆?br> 首先我們重新了解一下定時器的用法
JavaScript提供了定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInterval()這兩個函數(shù)來完成,用法如下

setTimeout()

指定某個函數(shù)或者代碼段,在多少毫秒內(nèi)執(zhí)行,會返回一個編號,編號可以用來取消這個定時器

var timer = setTimeout(func | code ,delay)
console.log(1);
setTimeout('console.log(2)',1000);
console.log(3);
//輸出 1 3 2  因為setTimeout指定第二行語句推遲1000毫秒再執(zhí)行

需要注意的是,推遲執(zhí)行的代碼必須以字符串的形式,放入setTimeout,因為引擎內(nèi)部使用eval函數(shù),將字符串轉(zhuǎn)為代碼。如果推遲執(zhí)行的是函數(shù),則可以直接將函數(shù)名,放入setTimeout。一方面eval函數(shù)有安全顧慮,另一方面為了便于JavaScript引擎優(yōu)化代碼,setTimeout方法一般總是采用函數(shù)名的形式,就像下面這樣。

setTimeout(function (){console.log(2)},1000);

setInterval()

setInterval函數(shù)的用法與setTimeout完全一致,區(qū)別僅僅在于setInterval指定某個任務(wù)每隔一段時間就執(zhí)行一次,也就是無限次的定時執(zhí)行。

var i = 1
 var timer = setInterval(function() {
   console.log(i++);
 }, 1000);

定時器有觸發(fā)就有停止


setTimeout和setInterval函數(shù),都返回一個表示計數(shù)器編號的整數(shù)值,將該整數(shù)傳入clearTimeout和clearInterval函數(shù),就可以取消對應(yīng)的定時器。

var id1 = setTimeout(f,1000);
var id2 = setInterval(f,1000);

clearTimeout(id1);  
clearInterval(id2);

1.異步
2.節(jié)流
首先我們了解一下什么是異步
我們js的運行機制,一般情況下是從上至下的執(zhí)行,這就是很舒服,讓人看起來也很容易理解,就比方有是一個保姆,每次做完一件事再去做一件事,那總會有一些特殊情況發(fā)生,比如說,保姆今天需要做的事是,打掃衛(wèi)生,拿快遞,買菜,做飯,但是這個保姆比較笨,快遞小哥打電話給他的時候?qū)λf:"麻煩你過三十分鐘的時候去樓下拿一下快遞,我準時到!",這個時候保姆就慌的一筆,這尼瑪那個時候我事做沒做完都不知道,他自然有自己的方法,對著小哥說:“那個麻煩你等一下,我需要把事情做完再去那快遞,所以我一會打電話給你你在30分鐘后到我樓下把”,沒辦法,快遞小哥只能同意了。這就是異步
就是把一件事放在最后面的做,并不和其他事攙和著同時去做,一件一件的完成,等做完了再去做剛才擱下的事(拿快遞)這個就是異步處理,也是單線程模型的特點,很多語言都是這個特點,比如php。
很費解,為什么說定時器很重要呢,因為定時器和我們的js異步處理是密不可分的

setTimeout('console.log(2)',0);
console.log(1);
console.log(3);

上述的代碼按照正常的邏輯是輸入的應(yīng)該是2,1,3
但是我們運行一下,就可以看出來,我們代碼運行的是 1,3,2
why


1.jpg

我們js開始渲染的時候會開辟兩個空間,一個是正常執(zhí)行空間,放置一般的代碼段,一個是任務(wù)隊列,他們會把認為耗時的,應(yīng)該在后面的函數(shù)或者代碼段放在任務(wù)隊列里面,也就是圖里面的webAPIs,DOM操作,ajax,定時器。等正常執(zhí)行空間執(zhí)行完成之后,再去執(zhí)行任務(wù)隊列里里面的任務(wù)?。ň秃帽茸詈竽每爝f一個意思)
帶著這個思想,我們再去理解一下上述代碼,首先計時器代碼被放置在任務(wù)隊列里面,等其他兩個console.log()執(zhí)行完成之后再去執(zhí)行定時器代碼

2.節(jié)流
我們定時器中的setTimeout被使用后是每隔一段時間觸發(fā)一次內(nèi)部函數(shù),我們可以使用某種暴力的手法暫時暫停setTimeout的運行,就是節(jié)流,仔細閱讀下段代碼

var flag;
function  f1(){
   if (flag) {
           clearTimeout(flag)
      }
 flag = setInterval(function(){
      console.log('我每隔一秒就執(zhí)行,除非你調(diào)用f1函數(shù)打斷我')
      },5000)
 }
f1();

這段代碼的意思就是首先申明一個變量flag
申明函數(shù)在f1()函數(shù)內(nèi)進行判斷,如果flag變量不為空就暫停計時器,為空就觸發(fā)計時器控制console.log打印內(nèi)容,并調(diào)用函數(shù)f1()
但是這個時候打開控制臺的時候就會發(fā)現(xiàn)控制臺每隔五秒輸出一次‘我每隔五秒就執(zhí)行,除非你調(diào)用f1函數(shù)打斷我',但是我們在控制臺輸入f1()回車的時候就會發(fā)現(xiàn)暫時停止打印了,但是五秒過后又出現(xiàn)了打印內(nèi)容。這個就是函數(shù)節(jié)流
函數(shù)節(jié)流我們可以理解成用一個小手法把定時器暫時停止

舉例說明:

  <input>

    docuemnt.querySelectorAll('input').addEventListener('keyup',function(){
        if(this.value === '') return
        if(this.timer) clearTimeout(this.timer)
        this.timer = setTimeout(()=>{
          console.log(this.value)
        },300)
    })    //實現(xiàn)一個300內(nèi)輸入支付不實行事件節(jié)流

           let oInput = document.querySelector('input')
                // oInput.addEventListener('input', function(e) {
                //     //如果直接每次onInput發(fā)請求,會導(dǎo)致性能問題
                //     console.log(e, this)
                // })

            oInput.addEventListener('input', debounce(callback, 500))

            function debounce(fn, delay) {
                let timer = null
                    // 綁定上下文this
                let self = this
                return function() {
                    let arg = arguments
                        // 每次清楚定時器
                    clearTimeout(timer)
                        // 重新打開定時器,做到只有最后一次執(zhí)行了
                    timer = setTimeout(() => {
                        // 綁定this,傳入?yún)?shù)給callback。通常我們需要事件對象就ok
                        fn.apply(this, arg)
                    }, delay)
                }
            }

            function callback(e) {
                console.log('觸發(fā)', e.target.value)
            }
//世界節(jié)流  停止輸出后一秒鐘打印信息
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容