js實現函數防抖與節流

概念理解

防抖:在事件被觸發n秒後再執行回調,若是在這n秒內又被觸發,則從新計時。ajax

節流:規定在一個單位時間內,只能觸發一次函數。若是這個單位時間內觸發屢次函數,只有一次生效。閉包

js函數防抖與節流的區別:app

函數防抖是某一段時間內只執行一次,而函數節流是間隔時間執行。ide

我的踩坑

一、經過理解函數防抖與函數節流的概念後,使用閉包實現函數防抖和節流,沒有考慮到對於節流,若是用戶在下一次請求以前已輸入完畢,可是此時不會再進行請求,則會致使最後輸入的文字獲取其餘事件改變不發請求,即漏請求,因此須要加一個setTimeout兜底函數,且在每次準備請求的時候,設一個flag,便是否已經發送請求,若是走了正常週期發送請求,改成true,不然即爲false,走setTimout,讓setTimeout比剩餘事件略長一些,優先走節流定時器請求;函數

二、若是是Input輸入事件,須要加入上面的超時兜底,若是是點擊事件節流,不須要加入超時兜底;this

三、若是使用箭頭函數,則不須要保存this。事件

代碼實現get

div>    <div>
        <input type="text" id="unDebounce">
    div>
    <div>
        <input type="text" id="debounce">
    div>
    <div>
        <input type="text" id="throttle">
    div>div>
// 函數防抖節流var elem1 = document.getElementById("unDebounce")var elem2 = document.getElementById("debounce")var elem3 = document.getElementById("throttle")// 不防抖function ajax1(value){
    console.log("不防抖,不節流")
    console.log(value)
}

elem1.addEventListener('keyup',function (e) {
    ajax1(e.target.value);
})// 防抖function ajax2(value) {
    console.log(value)
}function debounce(func,delay){
    console.log("函數防抖")
    let timer = null;    return function(...args){        if(timer){
            console.log("清除定時器")
            clearTimeout(timer)
        }
        timer = setTimeout(()=>{
            console.log("從新計時")
            func.call(this,...args)
        },delay)
    }
}
let debounceFn = debounce(ajax2,1000)
elem2.addEventListener('keyup',function (e) {
    debounceFn(e.target.value);
})// // 節流function ajax3(value){
    console.log(value)
}function throttle(func,delay){
    console.log("函數節流")
    let lastTime = 0;
    let timer = null;    return function (...args) {
        let flag = false ; // 還沒發送數據
        let now = +new Date().getTime();        if(timer){
            clearTimeout(timer)
        }        if(now-lastTime>=delay){
            console.log("當前時間大於設定時間,開始執行函數")
            func.apply(this,args)
            console.log("time1",new Date().getTime())
            lastTime = now;
            flag = true; // 發送了數據
        }else{
            timer = setTimeout(()=>{                if(!flag){ // 若是沒有發送數據成功,再走這個,兜底發送請求
                    func.apply(this,args)
                    console.log("time2",new Date().getTime())
                }
            },delay-(now-lastTime)+1000) // setTimeout多一些,優先執行週期性請求        }
    }
}
let throttleFn = throttle(ajax3,5000)
elem3.addEventListener('keyup',function (e) {
    throttleFn(e.target.value);
})
相關文章
相關標籤/搜索