修身养性,知行合一

  • 首页
  • 爱码
    • 系统
    • 数据库
    • JavaScript
    • CSharp
    • Python
  • 生活
    • 文化
    • 美食
  • 杂谈
  • 关于
修身养性,知行合一
码字,杂谈
  1. 首页
  2. 爱码
  3. 前端
  4. JavaScript
  5. 正文

手动实现JS节流

2020年6月24日 3460点热度 0人点赞 0条评论

什么是节流

在函数调用过程中,避免过于频繁的调用,而是间隔某一时间后调用一次的方法,叫做节流。

节流做什么

节流可以有效避免短时间内大量调用某一方法或数据,保证页面的稳定性和数据的准确性。

一个小的例子

使用 underscore 的节流功能来测试一下效果。

中文网址

在页面中直接导入 cdn 即可。

https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js

未节流时的样子

将下面内容粘贴到一个 HTML 的 body 标签中。

<div
  id="container"
  style="width:100%;height:200px;line-height:200px;text-align:center;color:#fff;background-color:#444;font-size:30px;"
></div>
<script>
  let count = 0;
  let container = document.querySelector("#container");

  // 此处为高频调用函数
  function doSomething() {
    container.innerHTML = count++;
  }

  container.onmousemove = doSomething;
</script>

这段代码会生成一个灰色框,只要鼠标在其内部移动,就会调用 doSomething 函数,导致数字不断增长。

使用节流

同样地,将下面内容粘贴到一个新的 HTML 的 body 标签中。

<div
  id="container"
  style="width:100%;height:200px;line-height:200px;text-align:center;color:#fff;background-color:#444;font-size:30px;"
></div>
<script src="https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js"></script>
<script>
  let count = 0;
  let container = document.querySelector("#container");

  // 此处为高频调用函数
  function doSomething() {
    container.innerHTML = count++;
  }

  container.onmousemove = _.throttle(doSomething, 300);
</script>

这里导入了 underscore 库,这个库会导出一个 _ 的对象,它包含一个 throttle 方法,该方法的作用就是节流。第一个参数是函数原型,第二个参数是响应时间,这里我们设置 300ms 后响应。

另外还可以设置是否第一次首先执行和最后一次是否执行,传入: {leading: false} 或 {trailing: false} 。当然,你也可以同时传入,但是需要注意,如果同时传入 false 的话,会出现 bug,该 bug 会导致下次启动时不响应 {leading: false} ,而是会立即执行第一次,这一点需要注意。

这次运行后,可以发现当鼠标移动时,不再一味地增加,而是每隔一段时间后(300ms)才会响应一次。

手动实现节流函数

利用时间戳方式

这样的方式会触发第一次,而不会触发最后一次。

function throttle(func, wait) {
  let context, args;
  let old = 0;
  return function () {
    context = this;
    args = arguments;
    let now = Date.now();

    if (now - old > wait) {
      // 立即执行
      func.apply(context, args);
      old = now;
    }
  };
}

利用定时器方式

这样的方式会触发最后一次,而不会触发第一次。

function throttle(func, wait) {
  let context, args, timeout;

  return function () {
    context = this;
    args = arguments;

    // 设置一个定时器,只有为空时才会触发,每次执行后都会重新设定一个定时器。
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null;
        func.apply(context, args);
      }, wait);
    }
  };
}

合并为最终的完整本版

利用上面的两种实现方式,可以得到一个比较完整的版本。

function throttle(func, wait, options) {
  let context, args, timeout, result;
  let previous = 0;

  if (!options) options = {};

  let later = function () {
    // 这里控制再次出发时,第一次是否执行,当为双false时,也是这里会出现的问题。
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };

  var throttled = function () {
    context = this;
    args = arguments;

    let now = Date.now();

    // 第一次不执行,调整previous的值即可。
    if (!previous && options.leading === false) previous = now;

    if (now - previous > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      // 立即执行
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      // 设置一个定时器,只有为空时才会触发,每次执行后都会重新设定一个定时器。
      timeout = setTimeout(later, wait);
    }

    return result;
  };

  throttled.cancel = function() {
      clearTimeout(timeout);
      timeout = null;
      timeout = context = args = null;
  }

  return throttled;
}
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: JavaScript
最后更新:2020年6月24日

jeremyjone

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

取消回复

文章目录
  • 什么是节流
  • 节流做什么
  • 一个小的例子
    • 未节流时的样子
    • 使用节流
  • 手动实现节流函数
    • 利用时间戳方式
    • 利用定时器方式
    • 合并为最终的完整本版
最新 热点 随机
最新 热点 随机
node-sass 的安装 解决端口被占的问题 vue3 组件 Props 的声明方式 给 div 添加选中状态 请求的取消 rgb 颜色小数兼容问题
node-sass 的安装
让Hyper-v与安卓虚拟机共存 C#使用Process的StandardOutput遇到阻塞的问题及解决方案 Windows下管理Linux格式硬盘 如何写一个组件级别的全局状态管理 清明小记 .NET6 的极简风格震撼到了我

(っ•̀ω•́)っ✎⁾⁾ 开心每一天

COPYRIGHT © 2021 jeremyjone.com. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

京ICP备19012859号-1

京公网安备 11010802028585号