Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

防抖和节流 #64

Open
coconilu opened this issue Sep 5, 2018 · 0 comments
Open

防抖和节流 #64

coconilu opened this issue Sep 5, 2018 · 0 comments

Comments

@coconilu
Copy link
Owner

coconilu commented Sep 5, 2018

前言

前端开发最注重的就是用户体验。但是用户往往在交互过程中体验到卡顿,那么就会很不愉快。

举几个例子:

  1. 当我们在window对象上注册了scroll事件,当我们轻轻拨动一下鼠标滚轮,会触发12次scroll事件处理器(在chrome浏览器上的测试数据),而如果我们在事件处理器里面占用了过多cpu,就会阻塞页面的渲染,也就是常说的页面卡顿。
  2. 不仅是scroll事件还有拖拽事件,也会有类似的情况
  3. 还有表单提交事件,跟上面两个情况不同的是,表单提交一般会涉及异步网络请求,当用户_手抖_多点了两次提交,那么就会请求两次服务器,一来增加服务器负担,而来也会因为要多执行几次回调而增加浏览器渲染页面的负担。

没办法,JavaScript就是单线程,我们得入乡随俗。解决方案是千千万的,但是这里仅提到其中的两种。

防抖(debounce)

概念:事件回调必须在事件发生的若干时间之后才会被执行。如果发生多个事件,则以最后一个事件为准。

实现方式:

闭包 + 异步回调模块,通用模板如下

export function debounce(interval, callback) {
  var timeout
  return () => {
    timeout && clearTimeout(timeout)
    timeout = setTimeout(() => {
      callback && callback()
    }, interval)
  }
}

通过简单修改,也可以变为仅触发第一次事件,若干时间间隔内不会再触发:

export function debounce(interval, callback) {
  var timeout, shouldRun = true
  return () => {
    if (!shouldRun) return
    shouldRun = false
    callback && callback()
    timeout = setTimeout(() => {
      shouldRun = true
    }, interval)
  }
}

这也就是节流的另一种写法。

节流(throttle)

概念:两个事件回调的执行之间有个最小间隔,换句话说,前面的事件回调执行完了之后,后面的事件回调会在最小间隔时间之后才能被执行。

实现方式:

闭包 + 异步回调模块,通用模板如下:

export function throttle(interval, callback) {
  var shouldRun = true
  return () => {
    shouldRun && callback && callback()
    shouldRun = false
    setTimeout(() => {
      shouldRun = true
    }, interval)
  }
}

节流和防抖结合

function throttle(fn, delay) {
  let last = 0, timer = null;
  return function () {
    let now = +new Date();
    if (now - last < delay) {
      clearTimeout(tiemr);
      timer = setTimeout(fn, delay);
    } else {
      last = now;
     clearTimeout(tiemr);
      fn();
    }
  }
}

参考:
轻松理解JS函数节流和函数防抖
JavaScript专题之跟着underscore学防抖
JavaScript专题之跟着 underscore 学节流

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant