1. 程式人生 > 實用技巧 >防抖和節流 (簡單易懂版)

防抖和節流 (簡單易懂版)

序言

"什麼是防抖? 什麼是節流?"

在學習這兩個知識點的時候總是會容易搞混哪個是防抖,哪個是節流。

其分別又代表著什麼含義,對於在不同的開發需求中如何合理的運用這兩個知識點尤為重要。

一、防抖

防抖,顧名思義就是"防止抖動"。

放在按鈕的點選事件中即指: 在指定的時間內,你在不停的點選按鈕,按鈕所繫結的事件處理函式只會在最後一次執行。

也就是當你點選完按鈕後,在指定時間內沒有再次觸發這個按鈕的點選,則當指定的時間到了之後,事件的處理函式也就會執行。

假如有一天中午你剛在工地搬完二十車的磚頭,你隱約聽到了汽車的鳴笛聲。

是它來了,運鈔車。它承載著你這一年的辛勞和淚水,今天是發工資的日子。

忙碌了一上午,你的雙手已經疲憊不堪,你不緩不慢的放下了手上的二十塊磚頭。

走向了那堆滿鈔票的隊伍前,等待著領取那屬於你的勞動成果。

隨著時間的流逝,輪到你了。工頭指著那一堆說,那堆是你的。

你用手臂拂去額頭的汗水,憨笑道:"誒,好嘞!",然後你拿起桌上的簽字筆準備簽署。

當你正想簽名的時候,你的手臂不知覺的抖動了起來,你知道,這種狀態下是沒辦法簽字了。

你的雙眼凝視著你的手臂,它還在不停的抖動。你的眼角泛起了一絲輕蔑:"呵!防抖, 不過爾爾!"

然後,嘴中默唸道:

// 簡易防抖函式
function debounce(fn, delay) {
  let timer = null;
  return function() {
    if (timer) {
      clearTimeout(timer);
      timer 
= setTimeout(fn, delay); } else { timer = setTimeout(fn, delay); } }; } // 以下為示例程式碼: // 簽名 function signature(){ document.write('張三') } // 呼叫防抖函式 debounce(signature, 3000)()

時間一秒,兩秒,三秒...終於!它停止了...

你以迅雷不及掩耳耳之勢,瀟灑的簽上了你的大名----"張三"。

二、節流

節流,顧名思義就是節約流水

放在按鈕的點選事件中即指: 在指定的時間內,你還是在不停的點選按鈕,按鈕所繫結的事件處理函式只會執行一次。

換成技能的冷卻時間可能會更好理解些:你點選某個技能之後它會進入冷卻,在冷卻期間無法再次觸發這個技能。

時間回到你簽完名字時的前二十分鐘。

你放下磚頭之後,看了看滿是磚土的雙手,又看了看不遠處的水龍頭,嘆息道:"怎麼又停水了..."

你略作思考,便朝著工地對面的公廁走去。

來到公廁門口,你看到一名約是九歲左右的孩童在洗手池中玩耍。你略微皺眉,快步走上前去。

當你正要斥責孩童的不懂事的時候,那名孩童先於你開口說話了。"你可知,何謂節流?"

你一頭霧水的走過來,心中奇怪這孩童怎地在此處玩耍還愛自言自語?

待你走近,方知原來孩童玩耍的水池中並無水跡,便開始懷疑公廁是不是也停水了。

正當你還在疑慮之中時,孩童又說話了。"我知道哪裡有水,但閣下須回答我一個問題"

"什麼問題?"

"何謂節流?"

"不知,還望賜教",你再次皺起了眉頭,稍加思索後答道。

"謂之節流,即節約流水。"

"隔壁這個水池的水龍頭是好的,你且洗著手並聽我道來"

(你的內心):"Hai..."

"就像這個帶感應功能的水龍頭一樣,手放上去之後水龍頭就會釋放水流出來,但是當過幾秒後水流就會停止"

"這就是節約流水,你把手再放上去,水流亦會再次被釋放"

"你在幾秒內來回將手放在感應器上,水流並不會隨之快速釋放/暫停,大體相似於此:"

// 簡易節流函式
function throttle(fn, delay) {
    let valid = null;
    return () => {
    if (valid) {
        return false;
    }
    valid = true;
    setTimeout(() => {
        fn();
        valid = false;
    }, delay);
    };
}

// 以下為程式碼示例
// 釋放流水
function releaseWater() {
  return "水"
}

// 呼叫節流
throttle(releaseWater, 1500)()

聽到這裡,你彷彿猶如醍醐灌頂,轉瞬便明白了其中門道,順便還請教了下什麼是"防抖"。

總結:

①防抖:指定時間內,多次操作只取最後一次操作

②節流: 指定時間內,多次觸發操作只會執行第一次

節流和防抖都有很多種,比如下面的立即執行版節流,但是萬變不離其宗,知道核心原理便可以一法通時萬法通

// 節流 - 立即執行版
function throttleRightNow(fn, delay) {
    let valid = null;
    return () => {
    if (valid) {
        return false;
    }
    valid = true;
    fn();
    setTimeout(() => {
        valid = false;
    }, delay);
    };
}