震驚!拉動一下控制檯大小,後臺請求數量爆炸,竟是沒做好防抖與節流!!

前言

最近有個朋友在面試過程中遇到一個問題:什麼是防抖節流?糟了,這可觸碰到我的知識盲區了,好像聽也沒聽過這2個東西,痛定思痛,趕緊學習學習。

“我自己是一名從事了6年web前端開發的老程序員(我的微信:web-xxq),今年年初我花了一個月整理了一份最適合2019年自學的web前端全套培訓教程(視頻+源碼+筆記+項目實戰),從最基礎的HTML+CSS+JS到移動端HTML5以及各種框架和新技術都有整理,打包給每一位前端小夥伴,這裏是前端學習者聚集地,歡迎初學和進階中的小夥伴(所有前端教程關注我的微信公衆號:web前端學習圈,關注後回覆“2020”即可領取)。
————————————————

 

 


防抖(debounce)

在事件被觸發n秒之後執行,如果在此期間再次觸發事件,則重新開始計時。

乍一看,這不是閒的蛋疼嗎?爲啥要等n秒之後再執行呢?

 

本着存在即合理的原則,咱看不懂但咱得去學啊!經過十秒鐘的思考,突然想起來之前做過的公司的一個小程序,使用的mpvue+vant-weappvan-field標籤並沒有和數據進行雙向綁定,而是每次都要觸發@input事件,從而完成數據綁定:

 

這就導致了一個問題:

 

輸一個手機號要觸發11次事件!!如果是聯想搜索的話。。。那畫面太美!

我們先自己想一下辦法來解決這個問題。

  • 首先我們需要在手機號輸入完成之後將數據綁定到phoneNumber上然後進行聯想搜索,怎麼算輸入完成呢,輸入一個數字到找到下一個數字輸入大概需要1不到秒,只要用戶一秒內沒有再次輸入,則將輸入框內容與phoneNumber綁定並進行聯想搜索(什麼?你說你輸入五個字符就停下?不怕後臺砍死你)
  • 準備工具:一個需要觸發的函數debounce、一個定時器、一個輸入框、一個判斷是否輸入完成的函數getPhone
  • 基本思路:輸入綁定事件getPhone,輸入之後開啓1秒定時器,如果在1秒內再次進行了輸入,則清除之前的定時器,並且重新設置定時器;如果1秒內沒有輸入,則輸入結束觸發事件a,進行聯想搜索。
<input id="phone" type="text"/>
複製代碼
// 需要觸發的函數
function debounce(d){
    console.log("聯想搜索phoneNumber:" + d)
}
let inp = document.querySelector("#phone");
// 輸入觸發的事件
function getPhone(fn,delay){
    let timer;
    // 使用閉包,保證每次使用的定時器是同一個
    return (d)=>{
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn(d);
            // 結束之後清除定時器
            clearTimeout(timer);
        },delay)
    }
}

let getPhoneDebounce = getPhone(debounce,1000);

inp.addEventListener('keyup',(e)=>{
    getPhoneDebounce(e.target.value);
})
複製代碼

這時候看輸出:

 

是的只輸出了一次號碼,也就是說不用每次輸入都進行一次搜索了。

 

節流(throttle)

如果持續觸發一個事件,則在一定的時間內只執行一次事件。

那麼問題來了,既然是持續觸發了,那爲啥還要設定一定時間內只執行一次呢?廢話,你吃雞爲啥不用AKM非要去追夢搶狗雜呢?還不是因爲AKM射速慢(狗雜真香)!

 

 

 

我們來試着做一個AKM的設計模擬:

  • 首先第一次點擊射擊的時候,打出一發子彈,當以極短的時間再次點擊射擊的時候,由於需要‘冷卻’——也就是節流,再次點擊無效,當冷卻時間過了之後,再次點擊射擊,則繼續下一次射擊
  • 準備工具:一個射擊的函數shot, 一個判斷射擊間隔是否結束的函數nextShot,一個觸發射擊的按鈕,判斷射擊是否結束的定時器timer
  • 基本思路:第一次點擊按鈕的時候,觸發shot,當繼續點擊的時候,射擊無效,只有過了定時器設置的時間纔可以繼續射擊。
<button id="shot">射擊</button>
複製代碼
function shot(){
    console.log('射擊')
}
let btn = document.querySelector('#shot');
function nextShot(fn,delay){
    let timer;
    // 閉包原理同上
    return ()=>{
        // 定時器存在,無法射擊
        if(timer){
            console.log('禁止射擊');
        }else{  // 定時器不存在,射擊,並設置定時器
            fn();
            timer = setTimeout(()=>{
                // 定時器結束,可以射擊
                clearTimeout(timer);
                timer = null;
            },delay)
        }
    }
}
let start = nextShot(shot,20);
btn.addEventListener('click',()=>{
    start();
})
複製代碼

當我們瘋狂點擊按鈕的時候:

 

 

可能這個例子不是很突出,我再說個類似的,英雄聯盟和DNF的技能冷卻應該更適合~

 

 

是時候迴歸一下標題了,免得有人說我可以去UC震驚部了

公司的大數據組件目前是隻要頁面大小發生變化就會重新加載,這就導致了有時候拉一下控制檯會發生很多次請求,這個時候就可以用防抖來解決一下了~

 

發佈了163 篇原創文章 · 獲贊 265 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章