目录

一、防抖 debounce

1. 概念

2. 应用场景

3. 使用 underscore 实现防抖

01 - 代码

02 - 效果

4. 实现

01 - 基本实现

代码

效果

02 - 优化 => this 和 参数绑定

代码

效果

03 - 优化 => 取消功能

代码

效果

04 - 优化 => 立即执行功能

代码

效果

05 - 优化 => 获取返回值

代码

06 - 最终版本

二、节流 throttle

1. 概念

2. 应用场景

3. 使用 underscore 实现节流

01 - 代码

02 - 效果

4. 实现

01 - 基本实现

代码

效果

02 - 优化 => this 和 参数的绑定

代码

效果

03 - 优化 => 立即执行功能

代码

效果

04 - 优化 => 获取返回值

代码

05 - 最终版本

5. 第二种方法实现节流


一、防抖 debounce

1. 概念

  • 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间
  • 当事件密集触发时,函数的触发会被频繁的推迟,并把上一次的给取消掉
  • 只有等待了一段时间也没有事件触发,才会真正的执行响应函数

2. 应用场景

  • 输入框中频繁的输入内容,搜索或者提交信息
  • 频繁的点击按钮,触发某个事件
  • 监听浏览器滚动事件,完成某些特定操作
  • 用户缩放浏览器的resize事件

3. 使用 underscore 实现防抖

01 - 代码

<body><input type="text" /><!-- 1. CDN引入: 网络的js文件 --><script src="https://cdn.jsdelivr.net/npm/underscore@1.13.4/underscore-umd-min.js"></script><script>// 2.获取input元素const inputEl = document.querySelector('input');// 3.防抖处理代码let counter = 1;inputEl.oninput = _.debounce(function () {console.log(`发送网络请求${counter++}:`, this.value);}, 1000);</script>
</body>

02 - 效果

4. 实现

01 - 基本实现

代码

<body><input type="text" /><script>function starDebounce(fn, delay) {// 1.用于记录上一次事件触发的timerlet timer = null;// 2. 返回新的函数return function () {// 3. 如果有再次触发(更多次触发)事件, 那么取消上一次的事件if (timer) clearTimeout(timer);// 4. 绑定当前事件timer = setTimeout(() => {// 5. 延迟后执行fn();// 6. 执行后把当前定时器删除timer = null;}, delay);};}</script><script>const inputDom = document.querySelector('input');let counter = 1;inputDom.oninput = starDebounce(function () {console.log(`发送网络请求${counter++}`);}, 1000);</script>
</body>

效果

02 - 优化 => this 和 参数绑定

代码

<body><input type="text" /><script>function starDebounce(fn, delay) {let timer = null;// 1. 返回新的函数,此时这个函数中的this为绑定的dom对象 => 相当于 inputDom的oninput指向这个函数// 2. 接受参数return function (...args) {if (timer) clearTimeout(timer);timer = setTimeout(() => {// 3. 绑定this,同时把参数传递给fnfn.apply(this, args);timer = null;}, delay);};}</script><script>const inputDom = document.querySelector('input');let counter = 1;inputDom.oninput = starDebounce(function (e) {console.log(`发送网络请求 :${counter++} => ${this.value} `, e);}, 1000);</script>
</body>

效果

03 - 优化 => 取消功能

代码

<body><input type="text" /><button>取消</button><script>function starDebounce(fn, delay) {let timer = null;// 1. 返回新的函数,此时这个函数中的this为绑定的dom对象 => 相当于 inputDom的oninput指向这个函数// 2. 接受参数const _debounce = function (...args) {if (timer) clearTimeout(timer);timer = setTimeout(() => {// 3. 绑定this,同时把参数传递给fnfn.apply(this, args);timer = null;}, delay);};// 3. 因为函数也是一个对象,所以_debounce.cancle = function () {if (timer) clearTimeout(timer);timer = null;};// 4. 返回函数return _debounce;}</script><script>const inputDom = document.querySelector('input');let counter = 1;const debounceFn = starDebounce(function (e) {console.log(`发送网络请求 :${counter++} => ${this.value} `, e);}, 1000);// 执行inputDom.oninput = debounceFn;// 取消const btnDom = document.querySelector('button');btnDom.onclick = debounceFn.cancle;</script>
</body>

效果

04 - 优化 => 立即执行功能

代码

<body><input type="text" /><button>取消</button><script>function starDebounce(fn, delay, immediate = false) {let timer = null;// 1. 是否是第一次执行let isInvoke = true;const _debounce = function (...args) {if (timer) clearTimeout(timer);// 2. 第一次操作不需要延迟if (immediate && isInvoke) {fn.apply(this, args);timer = null;isInvoke = false;return;}timer = setTimeout(() => {fn.apply(this, args);timer = null;// 3. 执行完后恢复isInvoke = true;}, delay);};_debounce.cancle = function () {if (timer) clearTimeout(timer);timer = null;// 3. 执行完后恢复isInvoke = true;};return _debounce;}</script><script>const inputDom = document.querySelector('input');let counter = 1;const debounceFn = starDebounce(function (e) {console.log(`发送网络请求 :${counter++} => ${this.value} `, e);},1000,true);// 执行inputDom.oninput = debounceFn;// 取消const btnDom = document.querySelector('button');btnDom.onclick = debounceFn.cancle;</script>
</body>

效果

05 - 优化 => 获取返回值

代码

<body><input type="text" /><button>取消</button><script>function starDebounce(fn, delay, immediate = false) {let timer = null;let isInvoke = true;const _debounce = function (...args) {// 1. 因为有延迟,使用promisereturn new Promise((resolve, reject) => {try {let res = null;if (timer) clearTimeout(timer);// 2. 第一次操作不需要延迟if (immediate && isInvoke) {// 2. 接受函数的返回值res = fn.apply(this, args);// 3. 传递出去resolve(res);timer = null;isInvoke = false;return;}timer = setTimeout(() => {res = fn.apply(this, args);// 3. 传递出去resolve(res);timer = null;// 3. 执行完后恢复isInvoke = true;}, delay);} catch (error) {reject(error);}});};_debounce.cancle = function () {if (timer) clearTimeout(timer);timer = null;// 3. 执行完后恢复isInvoke = true;};return _debounce;}</script><script>const debounceFn = starDebounce(function (name, text, age) {console.log(name, text, age);return '执行完了';}, 1000);// 4. 传递参数并接受返回值debounceFn('coder', 'star', 18).then((res) => {console.log(res);});// 取消const btnDom = document.querySelector('button');btnDom.onclick = debounceFn.cancle;</script>
</body>

06 - 最终版本

function starDebounce(fn, delay, immediate = false) {let timer = null;let isInvoke = true;const _debounce = function (...args) {return new Promise((resolve, reject) => {try {let res = null;if (timer) clearTimeout(timer);if (immediate && isInvoke) {res = fn.apply(this, args);resolve(res);timer = null;isInvoke = false;return;}timer = setTimeout(() => {res = fn.apply(this, args);resolve(res);timer = null;isInvoke = true;}, delay);} catch (error) {reject(error);}});};_debounce.cancle = function () {if (timer) clearTimeout(timer);timer = null;isInvoke = true;};return _debounce;
}

二、节流 throttle

1. 概念

  • 当事件触发时,会执行这个事件的响应函数
  • 如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数
  • 不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的

2. 应用场景

  • 监听页面的滚动事件
  • 鼠标移动事件
  • 用户频繁点击按钮操作
  • 轮播图的按钮滚动

3. 使用 underscore 实现节流

01 - 代码

<body><input type="text" /><!-- 1. CDN引入: 网络的js文件 --><script src="https://cdn.jsdelivr.net/npm/underscore@1.13.4/underscore-umd-min.js"></script><script>// 2.获取input元素const inputEl = document.querySelector('input');// 3.节流处理代码let counter = 1;inputEl.oninput = _.throttle(function () {console.log(`发送网络请求${counter++}:`, this.value);}, 1000);</script>
</body>

02 - 效果

4. 实现

01 - 基本实现

代码

<body><input type="text" /><script>/*** fn : 传入的函数* interval : 间隔的请求时间* 公式 : 等待时间 = 间隔时间 - ( 当前时间 - 开始时间 ) => interval - ( nowTime - startTime )** 等待时间 <= 0 即可执行函数*/function starThrottle(fn, interval) {// 1. 获取开始时间,赋初始值为0let startTime = 0;function throttle() {// 2. 获取当前时间const nowTime = new Date().getTime();// 3. 计算等待时间const waitTime = interval - (nowTime - startTime);// 4. 判断是否执行函数,第一次会默认执行if (waitTime <= 0) {fn();// 5.一旦执行完后,把当前时间赋值给开始时间startTime = nowTime;}}return throttle;}</script><script>// 2.获取input元素const inputEl = document.querySelector('input');// 3.节流处理代码let counter = 1;inputEl.oninput = starThrottle(function () {console.log(`发送网络请求${counter++}:`, this.value);}, 2000);</script>
</body>

效果

02 - 优化 => this 和 参数的绑定

代码

<body><input type="text" /><script>function starThrottle(fn, interval) {let startTime = 0;// 节流函数接受参数function throttle(...args) {const nowTime = new Date().getTime();const waitTime = interval - (nowTime - startTime);if (waitTime <= 0) {// 相当于 inputEl 直接调用该函数,所以this指向 inputEl// 把参数传给函数,即可在回调函数中拿到fn.apply(this, args);startTime = nowTime;}}return throttle;}</script><script>// 2.获取input元素const inputEl = document.querySelector('input');// 3.节流处理代码let counter = 1;inputEl.oninput = starThrottle(function (e) {// 使用console.log(`发送网络请求${counter++}:`, this.value, e);}, 2000);</script>
</body>

效果

03 - 优化 => 立即执行功能

代码

<body><input type="text" /><script>/*** fn : 传入的函数* interval : 间隔时间* immediate : 第一次是否执行,默认是马上执行的*/function starThrottle(fn, interval, immediate = true) {let startTime = 0;function throttle(...args) {const nowTime = new Date().getTime();// 如果immediate为false,且 开始时间为0时// 把当前时间赋值给开始时间,这样使得第一次不会执行if (!immediate && startTime === 0) {startTime = nowTime;}const waitTime = interval - (nowTime - startTime);if (waitTime <= 0) {fn.apply(this, args);startTime = nowTime;}}return throttle;}</script><script>// 2.获取input元素const inputEl = document.querySelector('input');// 3.节流处理代码let counter = 1;inputEl.oninput = starThrottle(function (e) {// 使用console.log(`发送网络请求${counter++}:`, this.value, e);},1000,false);</script>
</body>

效果

04 - 优化 => 获取返回值

代码

<script>function starThrottle(fn, interval, immediate = true) {let startTime = 0;function throttle(...args) {return new Promise((resolve, reject) => {try {const nowTime = new Date().getTime();// 如果immediate为false,且 开始时间为0时// 把当前时间赋值给开始时间,这样使得第一次不会执行if (!immediate && startTime === 0) {startTime = nowTime;}const waitTime = interval - (nowTime - startTime);if (waitTime <= 0) {// const res = fn.apply(this, args);resolve(res);startTime = nowTime;}} catch (error) {reject(error);}});}return throttle;}
</script><script>// 3.节流处理代码let counter = 1;const throttleFn = starThrottle(function (...e) {// 使用console.log(`发送网络请求${counter++}:`, e);return '无敌 												

JS高级 之 防抖 debounce - throttle 节流相关推荐

  1. 防抖debounce和节流throttle

    大纲 一.出现缘由 二.什么是防抖debounce和节流throttle 三.应用场景 3.1防抖 3.2节流 一.出现缘由 前端开发中,有一部分用户行为会频繁触发事件,而对于DOM操作,资源加载等耗 ...

  2. 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用

    函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 文章目录 函数防抖(debounce)和节流(throttle)在H5编辑器项目中的应用 1. 为什么要防抖节流 1.1 ...

  3. 探究防抖(debounce)和节流(throttle)

    本文来自我的博客,欢迎大家去GitHub上star我的博客 本文从防抖和节流出发,分析它们的特性,并拓展一种特殊的节流方式requestAnimationFrame,最后对lodash中的deboun ...

  4. 手写防抖(debounce)和节流(throttle)

    目录 测试代码 防抖(debounce) 基本功能实现 添加参数及this指向功能 第一次立即执行功能 取消功能 节流(throttle) 基本功能实现 增加this执向 最后一次在禁止时间段内是否执 ...

  5. Java版的防抖(debounce)和节流(throttle)

    概念 防抖(debounce) 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时 节流(throttle) 当持续触发事件时, ...

  6. 函数防抖(debounce)和节流(throttle)以及lodash的debounce源码赏析

    函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听.比如scroll resize等事件,这些事件在某些场景触发非常频繁. 比如,实现一个原生的拖拽功能(不能用 H5 Drag& ...

  7. 函数防抖debounce和节流throttle

    debounce 函数防抖 1.什么是函数防抖 函数防抖是优化高频率执行 js 代码的一种手段 可以让被调用的函数在一次连续的高频率操作过程中只被调用一次 2.函数防抖的作用 减少代码执行次数,提升网 ...

  8. 如何理解debounce(防抖)和throttle(节流)?

    节流 像阀门一样控制水流,避免单位时间内流量过大 防抖 防止抖动,比节流的流量控制效果更佳明显 在做远程搜索时,如果每输入1个字就调用1次接口,就会频繁查询数据库,假设我们的查询是"1234 ...

  9. 防抖(debounce)和节流(throttle)

    针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能.防抖和节流就是针对响应跟不上触发频率这类问题的两种解决方案 因此 ...

最新文章

  1. node和java性能_服务端I/O性能大比拼:Node、PHP、Java和Go(二)
  2. 金融数据信噪比的影响力又一力证
  3. wxWidgets:wxConfigBase类用法
  4. 用一年的时间,依靠SEO创造一个成功的网站
  5. c 复杂的前置后置面试题_你被哪些C语言面试题坑过?
  6. oracle同步数据adg_数据库周刊31丨华为openGauss 正式开源;7月数据库排行榜发布......
  7. 大规模数据生成 (500万条数据)
  8. K均值算法(K-means)
  9. php 调用speex解码库,怎么增加speex解码库
  10. 求两个数最大公因数的c语言程序
  11. 驾驶证机动车查询验证WebSerivce调用编程接口说明及示例代码
  12. 微软自带虚拟机Hyper—V启用
  13. layDate 时间范围限制 开始时间小于结束时间
  14. php仿携程网站,vue模拟携程官网的搭建
  15. 服务器ibm3650性能,IBM System x3650 M3系列参数、功能、性能_IBM System x3650 M3系列服务器配置_太平洋产品报价...
  16. 原码、反码、补码之间的快速转换和简单运算
  17. EE专业申请计算机工程,美国大学EE专业分支方向介绍及申请难度分析
  18. Java 并发在项目中的使用场景
  19. 西安邮电大学计算机学院系主任,计算机学院邀请西安邮电大学郑东教授和兰州大学金龙教授来校作学术报告...
  20. quartz集群模式任务触发分析(二)

热门文章

  1. 怎么给网站申请免费的SSL证书,简单几步就能完成
  2. uni-app 小程序生命周期
  3. 京东方EV116FHM-N10雾面屏 11.6寸LED背光液晶屏
  4. Excel导入时,日期格式的判断 isCellDateFormatted(Cell cell)不成功原因
  5. 为什么说php是c写的,Phper 学 C 兴趣入门 - 为什么 php 手册里经常说某个字符串函数是二进制安全的...
  6. 将像素动画软件Aseprite文件导入到Unity2019
  7. Qt编写地图综合应用56-实时动态轨迹
  8. 内存频率修改-技嘉Z390主板
  9. 法国新总统马卡龙的开源Web平台架构
  10. 【方法】数据增强(Data Augmentation)