js防抖和节流 - 青蓝鱼的博客-没有bug的代码是不完美的
侧边栏壁纸
  • 累计撰写 27 篇文章
  • 累计收到 16 条评论

js防抖和节流

admin
2022-03-16 / 7 评论 / 48 阅读 / 正在检测是否收录...

js防抖

什么是函数防抖

概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

应用场景

(1) 用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次的查询ajax请求,这样可以有效减少请求次数,节约请求资源;

(2) window的resize、scroll事件,不断地调整浏览器的窗口大小、或者滚动时会触发对应事件,防抖让其只触发一次;

function debounce(fn, delay) {
    let timer
    return function(arges) {
        clearInterval(timer);
        timer = setTimeout(() => {
            fn();
        }, delay)
    }
}

js节流

什么是节流

规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

应用场景

(1)鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;

(2)在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;

(3)监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;

function throttle(fn, delay) {
    let timer;
    return function() {
        if (!timer) {
            timer = setTimeout(() => {
                timer = null
                fn()
            }, delay);
        }
    }
}

和防抖区别是,防抖是间隔时间后最后执行一次,节流是按间隔时间连续执行.
时间戳截流——首节流
用最新触发的时间减去上一次回调执行的时间,如果大于等于 wait 则会执行回调

时间戳节流在第一次触发时会立刻执行。

在第一次操作的时候就会执行一遍fn,之后的操作如果时间不超过delay(例如2s)就不会在执行函数,理解为第一次执行,最后一次不执行

function throttle(func, wait) {
  let previous = 0
  return function throttled(...args) {
    const ctx = this
    const now = Date.now()
    const remain = wait - (now - previous)
    if (remain <= 0) {
      func.apply(ctx, args)
      previous = now
    }
  }
}

定时器节流——尾节流
指定时间之后执行回调,触发一个定时器之后,即使再次触发节流函数,也不会导致定时器推迟执行(事件循环或者同步阻塞会导致延迟执行,在这里不用考虑)。它不会清除已经开始的定时器,而是等待定时器被执行之后才再开始下一个定时器。

理解为第一次不执行,最后一次执行

function throttle(func, wait) {
  let timeout = 0
  return function throttled(...args) {
    const ctx = this
    // 如果已经是定时器定时阶段,则直接跳过,相当于忽略了触发
    // 必须等到定时器到时间之后
    if (!timeout) {
      timeout = setTimeout(() => {
        func.apply(ctx, args)
        timeout = null
      }, wait)
    }
  }
}

兼顾型节流,就能够在第一次,最后一次都执行代码。

function throttle(fn, delay){
    let last=0;
    let timer=null;

    return function(){
        let now=Date.now();
        let reming=delay-(now-last);

        clearTimeout(timer);//不管三七二十一,有定时器都先清除定时器
        if(reming<0){
            fn.apply(this, arguments);
            last=now;
        }else{
            timer=setTimeout(()=>{
                fn.apply(this,arguments);
            }, reming);
        }
    }
}
本文共 675 个字数,平均阅读时长 ≈ 2分钟
0

打赏

评论 (7)

取消
  1. 头像
    hhh
    湖北省 Windows 10 · FireFox
    沙发

    画图

    回复 删除 垃圾
    1. 头像
      hhh
      湖北省 Windows 10 · FireFox
      @ hhh

      hello word

      回复 删除 垃圾
  2. 头像
    hhh
    湖北省 Android · Google Chrome
    板凳

    666

    回复 删除 垃圾
  3. 头像
    111
    湖北省 Android · Google Chrome
    地毯

    学到了

    回复 删除 垃圾
  4. 头像
    aaa
    湖北省 Android · Google Chrome
    第4楼

    666

    回复 删除 垃圾
  5. 头像
    zzz
    湖北省 Android · Google Chrome
    第5楼

    画图

    回复 删除 垃圾
  6. 头像
    kkk
    Android · Google Chrome
    第6楼

    666表情

    回复 删除 垃圾