亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript的防抖和節(jié)流一起來了解下

 更新時(shí)間:2022年03月11日 15:04:16   作者:南梔~zmt  
這篇文章主要為大家詳細(xì)介紹了JavaScript的防抖和節(jié)流,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

1. 前言

首先來舉個(gè)例子。百度首頁的百度輸入框,用戶輸入的時(shí)候,每次輸入的信息,我們都能看到百度服務(wù)器返回給我們的聯(lián)想關(guān)鍵字。我們每改動(dòng)一個(gè)字,它就換一次聯(lián)想詞,這是我們?nèi)庋勰芸吹降乃俣?,?shí)際上如果不加以處理,可能已經(jīng)上服務(wù)器發(fā)起了好幾十次的同一個(gè)關(guān)鍵字聯(lián)想請(qǐng)求了,具體速度依賴于不同的pc等機(jī)器上的運(yùn)行速度不同。那么,剛剛也談到,對(duì)于同一個(gè)關(guān)鍵字,請(qǐng)求這么多次,也許想給用戶呈現(xiàn)的就一次,剩下的請(qǐng)求都是浪費(fèi)的,并且如果成千上萬甚至上億的用戶同時(shí)請(qǐng)求,對(duì)服務(wù)器的負(fù)擔(dān)是巨大的。

防抖節(jié)流解決的問題:

在連續(xù)觸發(fā)的事件中,事件處理函數(shù)的頻繁調(diào)用會(huì)加重瀏覽器或服務(wù)器的性能負(fù)擔(dān)導(dǎo)致用戶體驗(yàn)糟糕,有哪些連續(xù)觸發(fā)的事件呢 ?

比如,瀏覽器滾動(dòng)條的滾動(dòng)事件、瀏覽器窗口調(diào)節(jié)的resize事件、輸入框內(nèi)容校驗(yàn)以及在移動(dòng)端的touchmove事件等。

所以,我們將采用防抖函數(shù)(debounce )和節(jié)流函數(shù)(throttle)來限制事件處理函數(shù)的調(diào)用頻率

總的來說:防抖函數(shù)(debounce )和節(jié)流函數(shù)(throttle)是在時(shí)間軸上控制函數(shù)的執(zhí)行次數(shù)。

2. 函數(shù)防抖(debounce)

延遲防抖

延遲防抖(debounce): 在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計(jì)時(shí)。

生活中的實(shí)例: 如果有人進(jìn)電梯(觸發(fā)事件),那電梯將在10秒鐘后出發(fā)(執(zhí)行事件監(jiān)聽器),這時(shí)如果又有人進(jìn)電梯了(在10秒內(nèi)再次觸發(fā)該事件),我們又得等10秒再出發(fā)(重新計(jì)時(shí))。

當(dāng)持續(xù)觸發(fā)事件時(shí),一定時(shí)間段內(nèi)沒有再觸發(fā)事件,事件處理函數(shù)才會(huì)執(zhí)行一次。

如果設(shè)定的時(shí)間到來之前,又一次觸發(fā)了事件,就重新開始延時(shí)。

如下圖,持續(xù)觸發(fā)click事件時(shí),并不執(zhí)行handle函數(shù),當(dāng)1000毫秒內(nèi)沒有觸發(fā)click事件時(shí),才會(huì)延時(shí)觸發(fā)click事件。

在這里插入圖片描述

前緣防抖

執(zhí)行動(dòng)作在前,然后設(shè)定周期,周期內(nèi)有事件被觸發(fā),不執(zhí)行動(dòng)作,且周期重新設(shè)定。

為什么要這樣呢?

試想第一種延遲debounce,我們本來想對(duì)用戶輸入的關(guān)鍵字,發(fā)起請(qǐng)求聯(lián)想的頻率降低,但是如果用戶在我們?cè)O(shè)定的時(shí)間中,一直輸入,導(dǎo)致的就是,用戶一直看不到關(guān)鍵字,我們倒不如第一次輸入的時(shí)候就發(fā)起一個(gè)請(qǐng)求,服務(wù)器返回結(jié)果,呈現(xiàn)給用戶,然后后續(xù)用戶的鍵入結(jié)束在繼續(xù)請(qǐng)求)。

在這里插入圖片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>防抖</title>
</head>
<body>
    <button id="debounce1">點(diǎn)我防抖吶!</button>
<script>
    function handle() {
      console.log("防抖成功!");
    }
    window.onload = function() {
        // 1. 獲取按鈕,并綁定事件
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',debounce(handle,1000,true));
    }
    // 防抖函數(shù)
    function debounce(fn,wait, immediate ){
        //2. 設(shè)置時(shí)間戳,使用setTimeout讓返回函數(shù)延遲執(zhí)行
        let timer, result;
        return function(...args){
            // 3. timer存在,將定時(shí)器中的函數(shù)清除
            if(timer) clearTimeout(timer);
            // 4.1 立即執(zhí)行返回函數(shù)
            if(immediate){
                if(!timer){
                    result = fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    timer = null;
                },wait);
            }else{  // 4.2 非立即執(zhí)行返回函數(shù)
                timer = setTimeout(() => {
                    fn.apply(this,args);
                },wait);
            }
        }
        // 5. 立即執(zhí)行時(shí)返回函數(shù)的返回值
        return result;
    }
</script>
</body>
</html>

實(shí)現(xiàn)效果:

在這里插入圖片描述

原理解析:

  • 防抖函數(shù)作用,對(duì)傳入的函數(shù)進(jìn)行延時(shí)包裝后返回
  • setTimeout在前一次未執(zhí)行完前,第二次次觸發(fā)將會(huì)覆蓋掉前面的定時(shí)器,執(zhí)行第二次的功能
  • 前一次由于異步加延時(shí)還未執(zhí)行完,使用clearTimeout清除前面定時(shí)器,取消上次的fn功能
  • 為保持fn內(nèi)部this的指向,使用apply改變this指向
  • fn傳入為函數(shù),不是函數(shù)的調(diào)用

防抖函數(shù)實(shí)現(xiàn)總結(jié)

function debounce(fn,wait, immediate ){
    //2. 設(shè)置時(shí)間戳,使用setTimeout讓返回函數(shù)延遲執(zhí)行
    let timer, result;
    return function(...args){
        // 3. timer存在,將定時(shí)器中的函數(shù)清除
        if(timer) clearTimeout(timer);
        // 4.1 立即執(zhí)行返回函數(shù)
        if(immediate){
            if(!timer){
                result = fn.apply(this,args);
            }
            timer = setTimeout(() => {
                timer = null;
            },wait);
        }else{  // 4.2 非立即執(zhí)行返回函數(shù)
            timer = setTimeout(() => {
                fn.apply(this,args);
            },wait);
        }
    }
    // 5. 立即執(zhí)行時(shí)返回函數(shù)的返回值
    return result;
}

3. 函數(shù)節(jié)流(throttling)

throttling,節(jié)流的策略是,固定周期內(nèi),只執(zhí)行一次動(dòng)作,若有新事件觸發(fā),不執(zhí)行。周期結(jié)束后,又有事件觸發(fā),開始新的周期。 節(jié)流策略也分前緣和延遲兩種。

與debounce類似,延遲是指 周期結(jié)束后執(zhí)行動(dòng)作,前緣是指執(zhí)行動(dòng)作后再開始周期。

  • 節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率
  • 在持續(xù)觸發(fā)事件的過程中,函數(shù)會(huì)立即執(zhí)行,并且每n秒執(zhí)行一次

生活中的實(shí)例: 我們知道目前的一種說法是當(dāng) 1 秒內(nèi)連續(xù)播放 24 張以上的圖片時(shí),在人眼的視覺中就會(huì)形成一個(gè)連貫的動(dòng)畫,所以在電影的播放(以前是,現(xiàn)在不知道)中基本是以每秒 24 張的速度播放的,為什么不 100 張或更多是因?yàn)?24 張就可以滿足人類視覺需求的時(shí)候,100 張就會(huì)顯得很浪費(fèi)資源

延遲節(jié)流

在這里插入圖片描述

前緣節(jié)流

在這里插入圖片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>節(jié)流</title>
</head>
<body>
    <button id="debounce1">點(diǎn)我節(jié)流吶!</button>
<script>
    function handle() {
      console.log("節(jié)流成功!");
    }
    window.onload = function() {
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',throttling(handle,1000,false));
    }
    // 節(jié)流函數(shù)
    function throttling(fn,wait,immediate){
        let timer;
        return function(...args) {
            if(!timer){
                if(immediate){
                    fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    if(!immediate) {
                        fn.apply(this,args);
                    }
                    timer = null;
                },wait);
            }
        }
    }
</script>
</body>
</html>

實(shí)現(xiàn)效果:

在這里插入圖片描述

節(jié)流函數(shù)實(shí)現(xiàn)總結(jié)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>節(jié)流</title>
</head>
<body>
    <button id="debounce1">點(diǎn)我節(jié)流吶!</button>
<script>
    function handle() {
      console.log("節(jié)流成功!");
    }
    window.onload = function() {
        var myDebounce = document.getElementById('debounce1');
        myDebounce.addEventListener('click',throttling(handle,1000,false));
    }
    // 節(jié)流函數(shù)
    function throttling(fn,wait,immediate){
        let timer;
        return function(...args) {
            if(!timer){
                if(immediate){
                    fn.apply(this,args);
                }
                timer = setTimeout(() => {
                    if(!immediate) {
                        fn.apply(this,args);
                    }
                    timer = null;
                },wait);
            }
        }
    }
</script>
</body>
</html>

4. 兩者區(qū)別

函數(shù)節(jié)流不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定時(shí)間內(nèi)一定會(huì)執(zhí)行一次真正的事件處理函數(shù)。

函數(shù)防抖只是在最后一次事件后才觸發(fā)一次函數(shù)。

比如在頁面的無限加載場(chǎng)景下,我們需要用戶在滾動(dòng)頁面時(shí),每隔一段時(shí)間發(fā)一次 Ajax 請(qǐng)求,而不是在用戶停下滾動(dòng)頁面操作時(shí)才去請(qǐng)求數(shù)據(jù)。這樣的場(chǎng)景,就適合用節(jié)流技術(shù)來實(shí)現(xiàn)。

5. 應(yīng)用場(chǎng)景

對(duì)于函數(shù)防抖,有以下幾種應(yīng)用場(chǎng)景:

  • 給按鈕加函數(shù)防抖防止表單多次提交。
  • 對(duì)于輸入框連續(xù)輸入進(jìn)行AJAX驗(yàn)證時(shí),用函數(shù)防抖能有效減少請(qǐng)求次數(shù)。
  • 判斷scroll是否滑到底部,滾動(dòng)事件+函數(shù)防抖

總的來說,適合多次事件一次響應(yīng)的情況

對(duì)于函數(shù)節(jié)流,有如下幾個(gè)場(chǎng)景:

  • 游戲中的刷新率
  • DOM元素拖拽
  • Canvas畫筆功能

總的來說,適合大量事件按時(shí)間做平均分配觸發(fā)。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!   

相關(guān)文章

最新評(píng)論