<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一起來(lái)聊個(gè)五毛錢(qián)的么,防抖與節(jié)流 實(shí)現(xiàn)與應(yīng)用

          共 6978字,需瀏覽 14分鐘

           ·

          2021-05-15 16:59

          防抖與節(jié)流

          導(dǎo)讀目錄

          • 防抖(debounce)

            • 防抖應(yīng)用場(chǎng)景

            • 非立即執(zhí)行版

            • 立即執(zhí)行版本

            • 合成版本 防抖

          • 節(jié)流

            • 節(jié)流應(yīng)用場(chǎng)景

            • 時(shí)間戳版本

            • 定時(shí)器版本

          • 總結(jié)

            • 參考


          1防抖(debounce)

          所謂防抖,就是指觸發(fā)事件后 n 秒后才執(zhí)行函數(shù),如果在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)執(zhí)行時(shí)間。

          防抖類(lèi)型分為

          1. 非立即執(zhí)行版
          2. 立即執(zhí)行版
          3. 合成版本 防抖

          防抖應(yīng)用場(chǎng)景

          • 登錄、發(fā)短信等按鈕避免用戶(hù)點(diǎn)擊太快,以致于發(fā)送了多次請(qǐng)求
          • 調(diào)整瀏覽器窗口大小時(shí),resize 次數(shù)過(guò)于頻繁,造成計(jì)算過(guò)多,此時(shí)需要一次到位
          • 文本編輯器實(shí)時(shí)保存,當(dāng)無(wú)任何更改操作一秒后進(jìn)行保存

          非立即執(zhí)行版

          非立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)不會(huì)立即執(zhí)行,而是在 n 秒后執(zhí)行,如果在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)執(zhí)行時(shí)間。

          /**
           * @description
           * @param {*} func 觸發(fā)的時(shí)間
           * @param {*} wait 多少時(shí)長(zhǎng)才執(zhí)行事件
           * @return {*}
           */

                  function debounce(func, wait{
                      let timeout;
                      return function(){
                          // 獲取當(dāng)前作用域和參數(shù)
                          const context = this;
                          const args = [...arguments] 
                          // 如果當(dāng)前timeout 存在
                          // 清空定時(shí)器,再次等待wait時(shí)間過(guò)后再次執(zhí)行事件
                          if(timeout) clearTimeout(timeout)
                          // 定時(shí)執(zhí)行 傳遞進(jìn)來(lái)的事件
                          timeout = setTimeout(()=>{
                              func.apply(context,args)
                          },wait)  
                      }
                  }

          立即執(zhí)行版本

          立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)會(huì)立即執(zhí)行,然后 n 秒內(nèi)不觸發(fā)事件才能繼續(xù)執(zhí)行函數(shù)的效果。

          function debounce(func,wait{
            let timeout;
            return function ({
                const context = this;
                const args = [...arguments];
                if (timeout) clearTimeout(timeout);
                const callNow = !timeout;
                timeout = setTimeout(() => {
                    timeout = null;
                }, wait)
                if (callNow) func.apply(context, args)
            }
          }

          代碼解析

          當(dāng) 執(zhí)行 debounce 函數(shù)時(shí), 第一次進(jìn)來(lái)時(shí),timeout 為false,所以 callNow 的值 為 true ,那么它會(huì)立即執(zhí)行 func 函數(shù),這時(shí) timeout 的值 為 true , 當(dāng) timeout 值為true 時(shí), 會(huì)執(zhí)行 清空定時(shí)器,此時(shí) timeout 又為 false 了 , 這時(shí) callNow  又 為 true ,再次執(zhí)行 func 函數(shù)。

          一直循環(huán)這樣的操作:

          當(dāng) timeoutfalse 時(shí),會(huì)立刻執(zhí)行 func 函數(shù)。

          當(dāng) timeouttrue 時(shí),它會(huì)執(zhí)行clearTimeOut ,這時(shí)timeout 又為 false,  而 callNow  = ! timeout , 就會(huì)立刻執(zhí)行 func 函數(shù)了。

          合成版本 防抖

          通過(guò)傳遞 Boolean 來(lái)決定執(zhí)行哪種版本。

          • true 為立即執(zhí)行版
          • false 為非立即執(zhí)行版本

          debounce(func,1000,true)

          /**
           * @desc 函數(shù)防抖
           * @param func 函數(shù)
           * @param wait 延遲執(zhí)行毫秒數(shù)
           * @param immediate true 表立即執(zhí)行,false 表非立即執(zhí)行
           */

          function debounce(func, wait, immediate{
            let timeout;
            return function ({
              const context = this;
              const args = [...arguments];
              if (timeout) clearTimeout(timeout);
              if (immediate) {
                const callNow = !timeout;
                timeout = setTimeout(() => {
                  timeout = null;
                }, wait)
                if (callNow) func.apply(context, args)
              }
              else {
                timeout = setTimeout(() => {
                  func.apply(context, args)
                }, wait);
              }
            }
          }

          2節(jié)流

          所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)。 節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率。

          節(jié)流有兩種實(shí)現(xiàn):

          1. 時(shí)間戳版本
          2. 定時(shí)器版本

          節(jié)流應(yīng)用場(chǎng)景

          1. scroll 事件,每隔一秒計(jì)算一次位置信息等
          2. 瀏覽器播放事件,每個(gè)一秒計(jì)算一次進(jìn)度信息等
          3. input 輸入框在搜索內(nèi)容時(shí),可以控制多少s 在執(zhí)行請(qǐng)求,避免多次發(fā)起請(qǐng)求,節(jié)約性能。

          時(shí)間戳版本

          function throttle(func, wait{
              var previous = 0;
              return function({
                  let now = Date.now();
                  let context = this;
                  let args = arguments;
                  if (now - previous > wait) {
                      func.apply(context, args);
                      previous = now;
                  }
              }
          }

          定時(shí)器版本

          function throttle(func, wait{
              let timeout;
              return function({
                  let context = this;
                  let args = arguments;
                  if (!timeout) {
                      timeout = setTimeout(() => {
                          timeout = null;
                          func.apply(context, args)
                      }, wait)
                  }

              }
          }

          代碼解析

          當(dāng)執(zhí)行 throttle 函數(shù)時(shí),timeout 默認(rèn)為undefined , 此時(shí),! timeouttrue 時(shí),執(zhí)行 定時(shí)器,并且 將 timeout 為 null,即為false, 再次執(zhí)行throttle 函數(shù)時(shí),!timeout 又為 true ,再次執(zhí)行定時(shí)器。

          **通過(guò) timeout  的狀態(tài)來(lái)達(dá)到節(jié)流的控制 **

          3總結(jié)

          • 防抖:觸發(fā)事件后,一定時(shí)間后再執(zhí)行事件,可以立即執(zhí)行 也可以一定時(shí)間再執(zhí)行

          • 節(jié)流:控制流量,在單位時(shí)間內(nèi)只能請(qǐng)求一次,避免多次觸發(fā)事件,影響服務(wù)器性能。

          參考

          https://github.com/mqyqingfeng/Blog/issues/26


          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  手机av在线| 日本道久久 | 日本无码中文字幕乱码aⅴ的特色 | 日本成人在线午夜影院 | 国产自产21区 |