超級簡單的防抖與節流

1340.640.jpg

前言

之前準備面試、看面經的時候,總會在內心罵,怎麼這麼多沙雕題目,這不是特地爲難我胖虎嗎
爲難胖虎.jpeg
參加工做一年多了,發現不少面試題在工做中真的會明的暗的碰到。
能讓我等菜鳥提早知道這麼多概念,爲咱們指明debbug的方向,真是煞費了前人的一番苦心呀。css

這兩天遇到一個bug正好是利用節流的思想解決的,趁此機會正好把我對防抖節流思想的理解和應用整理一下,寫出了,但願能在工做和麪試中幫到你們html

防抖(debounce)和節流(throttle)很容易搞混,定義極其晦澀。所以咱們先從應用場景入手vue

防抖(debounce)

應用場景

debounce.gif

在輸入文字的時候咱們進行某些處理,若是直接綁定處理函數,則每次輸入都會處理一次,形成性能浪費,咱們實際但願的是用戶輸入完了或者暫時輸入完了咱們再去處理,因此須要給定一個延遲時間,而後若是一直輸入咱們一律不斷去刷新這個延遲時間,直到中止輸入了再延遲處理ios

實現

debounce函數挺簡單的,就是一個延遲執行,和刷新延遲功能,用Js的定時器和清除定時器很容易搞定,寫個超級簡單的版本面試

未防抖:<input type="text" oninput="handleInput()">
防抖處理後:<input type="text" oninput="debounce(handleInput,300)()">
function debounce (fn,delay){
    return function () {
        fn.tid && clearTimeout(fn.tid)
        fn.tid=setTimeout(fn,delay)
    }
}

節流(throttle)

應用場景

登陸按鈕,用戶登陸的時候點一下,假設報錯,帳號密碼錯誤
若是用戶手賤,一直狂點,會一直出提示,須要優化一下,先看下效果
未使用節流:重複動做忒多
未節流.gif
未使用節流:動做必定時間內只執行一次
節流.gifelement-ui

實現

怎麼實現throttle(fn,delay)這個函數呢,單位時間內只能執行一次,換句話說當前執行的時候與前一次執行時間差必須大於delay才讓執行
咱們要保存上一次執行時間,咋保存呀?經過閉包
寫個超級簡單的,網上看了其餘幾我的的,好像和我不太同樣if後面還跟了個else,使單位時間後還會執行一次,這個就看我的需求啦哈哈哈,主體邏輯絕壁是我這個,你們放心大膽抄,原創axios

throttle(fn,interval){
            let lastTime = new Date().getTime()//閉包保存上一次時間,注意這個函數執行的時候LastTime就存在了,因此通常點擊的時候再觸發,fn基本會執行,也就是先執行一次,而後單位時間執行一次
            return function () {
                let currentTime = new Date().getTime()
                if(currentTime-lastTime>interval){
                    fn()
                    lastTime = currentTime
                }
            }
        }

完整代碼後端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入組件庫 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>

<div id="app">
    未節流:<el-button @click="handleLogin">login</el-button><br/><br/><br/>
    節流:<el-button @click="throttleHandleLogin">login</el-button>
</div>

<script >
new Vue({
    el: '#app',
    data: function(){
        return {
            throttleHandleLogin: this.throttle(this.handleLogin,2000)
        }
    },
    methods: {
        handleLogin(){
            this.$message({message:'帳號密碼錯誤',type:'error'})
        },
        throttle(fn,interval){
            let lastTime = new Date().getTime()
            return function () {
                let currentTime = new Date().getTime()
                if(currentTime-lastTime>interval){
                    fn()
                    lastTime = currentTime
                }
            }
        }
    }
})


</script>

</body>
</html>

問你們一個問題,爲何我會把throttleHandleLogin寫在data裏面?寫在methods裏面行不行?想知道答案的點贊留言閉包

防抖節流區別

看起來防抖節流都是解決動做重複觸發產生的性能問題的,可是他們的原理是不一樣的
debounce 是延遲執行,刷新延遲(理論上若是我一直動是否是能夠一直不執行?)
throttle 是馬上執行,間隔執行,(單位時間確定得執行,應該不會有人會無聊到把間隔時間設置爲無限長吧)
因此區別能夠記成,當動做一直持續下去,函數會不會執行。debounce不會,throttle會app

仍是記不住區別的記使用場景吧

解決一個開發問題

如今運用咱們所學解決上個星期我遇到的一個場景
我在axios裏面有個響應攔截器,遇到後端返回的狀態碼爲xx(沒有權限)會跳到登陸頁,報錯沒有權限
可是有個問題,在某些頁面我會不止發一個請求,每一個請求都會受到沒有權限的響應引發報錯,因此跳到登陸頁我會受到N個沒有權限的提示
初級知識盲區.png

怎麼作?用debounce仍是throttle?

我用的throttle解決的,3秒內若是是權限問題,只讓報一次錯

//fn是權限錯誤的相關邏輯
const throttlefn = throttle(fn,3000,{trailing:false})
service.interceptors.response.use(
  async res => {
    if (!res.data) return null
    const { data: { msg, status } } = res
    switch (status) {
      case OK:...
      case NOT_LOGIN:case LoginFailed:case InvalidRole:case INVALID_PWD:
        throttlefn(msg)
        break
      case NONE_DATA:...
      default:...
    }
  },...)

結尾

今天關於節流防抖的優化就分享到這了。因爲技術有限,若是閱讀中發現有什麼錯誤,請在留言指出 若是你以爲本文對你有很大的幫助,求點贊,求收藏,求打賞,大家的支持是做者寫做的最大動力!

相關文章
相關標籤/搜索