蝦扯蛋之函式防抖和節流

逍遙自在0121發表於2018-07-11

背景

    今天在coding的時候,做了一個搜尋框,也正是這個搜尋框,讓我和後臺小夥伴直接由鐵磁變為塑料兄弟。那到底發生啥了呢?其實很簡單,其實很無奈,就是我用王者的手速把他的介面訪問崩了!

    我們在平時開發的時候,會有很多場景會頻繁觸發事件,比如說搜尋框實時發請求,onmousemove,resize,onscroll等等,有些時候,我們並不能或者不想頻繁觸發事件,咋辦呢?這時候就應該用到函式防抖和函式節流了!

函式防抖(debounce)

    什麼是防抖?短時間內多次觸發同一個事件,只執行最後一次,或者只在開始時執行,中間不執行。舉個栗子:你去乘坐公交車,不停地上人,連續上人的過程中司機師傅是不會開車的,只有當最後一個人上車了,老司機才會開車!嘿嘿嘿!我們以不停地觸發onmousemove事件,讓數字+1為例。程式碼如下:

  • 不使用防抖和節流,數字會像得了羊癲瘋一樣不停地增長
//變數初始化
var xcd = document.getElementById('xcd'),
    count = 1; 
//要執行的操作 數字+1
function doSomething() {
    xcd.innerHTML = count++;
};
//觸發onmousemove事件 正常情況下
xcd.onmousemove = doSomething;
複製程式碼

蝦扯蛋之函式防抖和節流

  • 使用防抖之綠色基礎版
//綠色基礎版:
function debounce(doSomething,wait){
    var timeout;//需要一個外部變數,為增強封裝,所以使用閉包
    return function(){
        var _this = this,
            _arguments = arguments;//arguments中存著e
        clearTimeout(timeout);
        timeout = setTimeout(function(){
            doSomething.apply(_this,_arguments);   
        },wait);
    }
}
//觸發onmousemove事件
xcd.onmousemove = debounce(doSomething,1000);
複製程式碼

蝦扯蛋之函式防抖和節流
    這個綠色基礎版雖然簡單,但是已經能夠解決大部分需求場景了,沒有啥特殊需求使用這個版本就行了!用起來簡直像吃了巴豆一樣,duangduangduang,極其通暢!But,還會有一些其他需求,比如我想立即執行,就是連續觸發事件的開始時立即執行一次,後連續觸發不執行,我們用isImmediate表示是否立即執行,程式碼如下:

  • 使用防抖之立即執行版
//立即執行版
function debounce(doSomething,wait,isImmediate){
    var timeout;
    return function(){
        var _this = this,
            _arguments = arguments;
        clearTimeout(timeout);
        if(isImmediate){
            var isTrigger = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            isTrigger&&doSomething.apply(_this,_arguments);
        }else{
            timeout = setTimeout(function(){
                doSomething.apply(_this,_arguments);   
            },wait);
        }
    }
}
//觸發onmousemove事件
xcd.onmousemove = debounce(doSomething,1000,true);
複製程式碼

蝦扯蛋之函式防抖和節流

函式節流(throttle)

    什麼是節流?節流是連續觸發事件的過程中以一定時間間隔執行函式。節流會稀釋你的執行頻率,比如每間隔1秒鐘,只會執行一次函式,無論這1秒鐘內觸發了多少次事件。

    舉個栗子:你每天要喝好多水,但是你不會每喝完一口水都要去一次廁所,如果有盆友是醬紫的話,我勸你還是去醫院看看吧→_→廁所看你都煩~你雖然一直在喝水,但是不會一直去廁所,通常的節奏是!喝水喝水喝水上廁所!喝水喝水喝水上廁所!雖然一直在觸發,但是每隔一段時間只會執行一次操作,這就是函式節流!

  • 使用節流之時間戳版
//綠色基礎版之時間戳版
function throttle(doSomething,wait){
    var _this,
        _arguments,
        initTime = 0;
    return function(){
        var now = +new Date();//將new date()轉化為時間戳
            _this = this;
            _arguments = arguments;
        if(now - initTime>wait){
            doSomething.apply(_this,_arguments);
            initTime = now;
        }
    }
}
//觸發onmousemove事件
xcd.onmousemove = throttle(doSomething,1000);
複製程式碼

蝦扯蛋之函式防抖和節流

  • 使用節流之定時器版
//綠色基礎版之定時器版
function throttle(doSomething,wait){
    var timeout;
    return function(){
        var _this = this;
            _arguments = arguments;
        if(!timeout){
            timeout = setTimeout(function(){
                timeout = null;
                doSomething.apply(_this,_arguments);
            },wait);
        };
    }
}
//觸發onmousemove事件
xcd.onmousemove = throttle(doSomething,1000);
複製程式碼

蝦扯蛋之函式防抖和節流
    同樣,以上兩個節流的綠色基礎版也可以滿足大多數需求場景啦!這兩個版本有什麼區別呢?時間戳版會在開始時立即執行一次,最後時間間隔內不再執行;定時器版開始時不執行,最後時間間隔內再執行一次。可以根據自己的實際需求選擇合適的版本。

    當然,可能還有一些BT的產品會問你,能不能先立即執行一次,中間固定間隔時間執行,最後在執行一次呢?這就到了裝B的時候了。像我這麼牛X的前端,必須的啊,把兩種合在一起就行了,雙修什麼的最喜歡了*@ο@*

蝦扯蛋之函式防抖和節流

  • 使用節流之雙劍合璧版
//節流之雙劍合璧版
function throttle(doSomething, wait) {
    var timeout, _this, _arguments,
        previous = 0;

    var later = function() {
        previous = +new Date();
        timeout = null;
        doSomething.apply(_this, _arguments)
    };
    var throttled = function() {
        var now = +new Date();
        //下次觸發 doSomething 剩餘的時間
        var remaining = wait - (now - previous),
            _this = this;
            _arguments = arguments;
         // 如果沒有剩餘的時間了
        if (remaining <= 0) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            doSomething.apply(_this, _arguments);
        } else if (!timeout) {
            timeout = setTimeout(later, remaining);
        }
    };
    return throttled;
}
//觸發onmousemove事件
xcd.onmousemove = throttle(doSomething,1000);
複製程式碼

蝦扯蛋之函式防抖和節流
深入理解函式防抖和節流,合理選擇防抖或節流,能解決很多帕金森疾病,實乃出門旅行,居家生活之必備良品!OK就醬,我就是我,我瞅自己都上火!不定期分享一些前端知識點和麵試點,喜歡點波關注唄!

蝦扯蛋之函式防抖和節流
參考:https://github.com/mqyqingfeng/Blog

相關文章