如何理解防抖和节流?

防抖和节流(详细) 使用场景和区别 1.防抖 (多次触发 只执行最后一次) 作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间 防抖类似于英雄联盟回城6秒,如果回城中被打断,再次回城需要再等6秒 实现代码: <body> <input type="text" id="inp"> <script> // 1.封装防抖函数 function debounce(fn, time) { 阅读详情

image

前端工程师们都听过看起来很高级的词,节流和防抖,其实节流就是throttle,防抖就是debounce,其实这个也属于前端性能优化的一部分。

  • 节流 像阀门一样控制水流,避免单位时间内流量过大
  • 防抖 防止抖动,比节流的流量控制效果更佳明显

在做远程搜索时,如果每输入1个字就调用1次接口,就会频繁查询数据库,假设我们的查询是"12345",不考虑用户输入错误的情况,至少会请求5次。

再思考一个问题,按钮的click重复触发(例如快速点击2次,3次,…n次)该如何在前端做一层拦截,避免发送重复请求到服务端,最常见的是新增时插入重复数据,这个问题该怎么办呢?

  • 查询是"12345",至少会请求5次导致频繁查询数据库
  • 有没有一种方法,可以隔个几百毫秒再去查询呢?(setTimeout)
  • 有没有更加高级的做法,用户输入完成后,停顿了几百毫秒再去查询呢?(debounce)
  • 有没有用户体验更加好的做法,不用等待漫长的等待时间从而响应更快呢?(throttle)
  • 快速点击2次,3次,…n次新增按钮导致插入重复数据
  • 如何避免用户单位时间内频繁点击按钮导致重复发送请求的问题?(debounce)
  • 有没有除了debounce之外的更加精准的方法?(loading)
  • debounce适用场景
  • throttle适用场景
  • debounce和throttle的对比
  • 手写一个debounce和throttle(setTimeout版本)
  • 手写一个throttle(不能使用setTimeout)

查询是"12345",至少会请求5次导致频繁查询数据库

<template>
  <input @input="handleInput"/>
</template>

<script>
export default {
  name: 'input',
  data() {
    return {
      delay: 1000,
      count: 0,
    };
  },
  methods: {
    handleInput(e) {
      console.log(`debounce wait时间为${this.delay}ms`);
      console.log('触发了input事件', e.target.value);
      this.count++;
      console.log(`触发了${this.count}次远程搜索`);
    },
  },
};
</script>

打印结果:
debounce wait时间为1000ms
触发了input事件 1
触发了1次远程搜索
debounce wait时间为1000ms
触发了input事件 12
触发了2次远程搜索
debounce wait时间为1000ms
触发了input事件 123
触发了3次远程搜索
debounce wait时间为1000ms
触发了input事件 1234
触发了4次远程搜索
debounce wait时间为1000ms
触发了input事件 12345
触发了5次远程搜索

说明:输入5个数查询5次,造成了频繁查询数据库的行为,是一种性能浪费。

有没有一种方法,可以隔个几百毫秒再去查询呢?(setTimeout)

有,可以为函数设置一个setTimeout函数,相当于定时调用接口,这种方法是低效的,也是非常愚蠢的,需要控制开关定时器,一旦搜索功能多了,就更蠢了。

有没有更加高级的做法,用户输入完成后,停顿了几百毫秒再去查询呢?(debounce)

有,debounce(防抖)就是做这个事情的,lodash从0.1.0就支持了这个方法。

<template>
  <input @input="debounceHandleInput"/>
</template>

<script>
import _ from 'lodash';

export default {
  name: 'input-debounce',
  data() {
    return {
      delay: 1000,
    };
  },
  computed: {
    debounceHandleInput() {
      return _.debounce(this.handleInput, this.delay);
    },
  },
  methods: {
    handleInput(e) {
      console.log(`debounce wait时间为${this.delay}ms`);
      console.log('触发了input事件', e.target.value);
      this.count++;
      console.log(`触发了${this.count}次远程搜索`);
    },
  },
};
</script>

打印结果:
debounce wait时间为1000ms
触发了input事件 12345

说明:在1000ms时间范围内触发,仅仅触发了一次远程搜索,也就是仅仅调用一次后端接口,达到我们的预期效果。

有没有用户体验更加好的做法,不用等待漫长的等待时间从而响应更快呢?(throttle)

<template>
  <input @input="throttleHandleInput"/>
</template>

<script>
import _ from 'lodash';

export default {
  name: 'input-throttle',
  data() {
    return {
      delay: 1000,
      count: 0,
    };
  },
  computed: {
    throttleHandleInput() {
      return _.throttle(this.handleInput, this.delay);
    },
  },
  methods: {
    handleInput(e) {
      console.log(`throttle wait时间为${this.delay}ms`);
      console.log('触发了input事件', e.target.value);
      this.count++;
      console.log(`触发了${this.count}次远程搜索`);
    },
  },
};
</script>

打印结果:
throttle wait时间为1000ms
触发了input事件 1
触发了1次远程搜索
throttle wait时间为1000ms
触发了input事件 12345

说明:在1000ms时间范围内触发,仅仅触发了2次远程搜索,调用2次后端接口。用户首次输入1立即返回数据,保证数据到达速度,也提升了用户体验。中间的12,123,1234被节流函数成功拦截避免触发。而12345是我们最终需要的搜索结果,在最后返回给用户。达到我们的预期效果。

快速点击2次,3次,…n次新增按钮导致插入重复数据

<template>
  <button @click="handleClick">新增</button>
</template>

<script>
export default {
  name: 'click',
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    handleClick(e) {
      console.log('触发了click事件', e.target.value);
      this.count++;
      console.log(`触发了${this.count}次新增数据`);
    },
  },
};
</script>

触发了click事件
触发了1次新增数据
触发了click事件
触发了2次新增数据

说明:快速点击2次“新增”按钮,而最终只触发了2次数据新增,造成重复数据插入。

如何避免用户单位时间内频繁点击按钮导致重复发送请求的问题?(debounce)

<template>
  <button @click="debounceHandleClick">新增</button>
</template>

<script>
import _ from 'lodash';

export default {
  name: 'click-debounce',
  data() {
    return {
      delay: 1000,
      count: 0,
    };
  },
  computed: {
    debounceHandleClick() {
      return _.debounce(this.handleClick, this.delay);
    },
  },
  methods: {
    handleClick(e) {
      console.log(`debounce wait时间为${this.delay}ms`);
      console.log('触发了click事件', e.target.value);
      this.count++;
      console.log(`触发了${this.count}次新增数据`);
    },
  },
};
</script>

打印结果:
debounce wait时间为1000ms
触发了click事件
触发了1次新增数据

说明:快速点击2次“新增”按钮,而最终只触发了1次数据新增,达到了我们的预期效果。

有没有除了debounce之外的更加精准的方法?(loading)

loading是指在异步请求完成(成功或者失败)前,开启loading,使得按钮或者用户界面处于“加载中”“转圈”“spin"这样的一个状态,从而禁止用户发起重复操作,异步请求完成后,关闭loading。

image

<template>
  <Button @click="loadingHandleClick" :loading="loading">新增</Button>
</template>

<script>
export default {
  name: 'click-loading',
  data() {
    return {
      loading: false,
      count: 0,
    };
  },
  methods: {
    loadingHandleClick(e) {
      this.loading = true;
      this.count++;
      console.log(`触发了${this.count}次新增数据`);
      console.log('发起异步请求,loding为:', this.loading);
      setTimeout(() => {
        console.log('异步请求执行了1s');
        this.loading = false;
        console.log('异步请求完成,loding为:', this.loading);
      }, 1000);
    },
  },
};
</script>

触发了1次新增数据
发起异步请求,loding为: true
异步请求执行了1s
异步请求完成,loding为: false

说明:第1次事件触发后,按钮处于loading为true状态,禁止用户触发,1秒后异步请求执行完成,loading为false,允许用户再次使用。因此都无法做到快速点击2次“新增”按钮,只能触发1次,重复的第2次触发用户无法触发,最终只触发了1次数据新增,达到了我们的预期效果。

debounce适用场景

  • Debouncing a click evnet to insert an uniq data
  • Debouncing a input event handler (this example explain this use case)
  • Debouncing a resize event handler

throttle适用场景

  • Throttling a input event handler (this example explain this use case)
  • Throttling a scroll event in infinite scroll(demo case)
  • Throttling a mousemove/touchmove event handler in canvas

debounce和throttle的对比

地址:http://demo.nimius.net/debounce_throttle/
图片:
image

通过在canvas上连续触发mousemove事件我们发现:

  • debounce只有当连续事件停止后的一小段时间后再触发一次,连续事件结束后可能只触发一次
  • throttle会在连续事件的过程中,每隔一段时间至少触发一次,连续事件结束后触发不止一次

手写一个debounce和throttle

const fn = (e, data)=> console.log(data)
const dbounceFn = debounce(fn, 2000)
const throttleFn = throttle(fn, 2000)
document.onmousemove = function(e) {
    dbounceFn(e, 'debounce');
}
document.onmousemove = function(e) {
    throttleFn(e, 'throttle');
}
手写一个debounce
function debounce(fn, delay){
    let timer;
    return function(){
        const _this = this;
        const args = arguments;
        if(timer) clearTimeout(timer);
        timer = setTimeout(()=>{
            fn.apply(_this, args); // _this.fn(args);
        }, delay)
    }
}
手写一个throttle
function throttle(fn, delay){
    let timer;
    return function(){
        const _this = this;
        const args = arguments;
        if(timer) return;
        timer = setTimeout(()=>{
            fn.apply(_this, args); // _this.fn(args);
            timer = null;
        }, delay)
    }
}

手写一个throttle(不能使用setTimeout)

function throttle(fn, delay){
    let lastTime = 0;
    return function(){
        const _this = this;
        const args = arguments;
        const currentTime = Date.now();
        if(currentTime - lastTime > delay){
            fn.apply(_this, args);
            lastTime = currentTime
        }
    }
}
let fn = (e,data)=>{console.log(e, e.offsetX, e.offsetY, data)}
let throttleFn = throttle(fn, 2000)
document.onmousemove = function(e){
    throttleFn(e, 'throttle')
}

期待和大家交流,共同进步

努力成为优秀前端工程师!

防抖(debounce) 和 节流(throttling) 防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 在给DOM绑定事件时,有些事件我们是无法控制触发频率的。 如鼠标移动事件onmousemove, 滚动滚动条事件onscroll,窗口大小改变事件onresize,瞬间的操作都会导致这些事件会被高频触发。 如果事件的回调函数较为复杂,就会导致响应跟不上触发,出现页面卡顿,假死现象。 在实时检查输入时,如果我们绑定onkeyup事件发请求去... 阅读详情

相关推荐

理解节流和防抖

文章目录前言一、区分防抖和节流二、防抖与节流的简单实现1.防抖的简单实现2.节流的简单实现总结参考资料 前言 节流和防抖是前端常见的性能优化的方法,网上对这个方法的有许多优秀的介绍,我在这里只是记录一下我对这些方法的一些理解。 一、区分防抖和节流 刚开始接触这两个概念的时候,一直区分不开,总是搞混。从使用场景和语义上理解,对于区分这两个概念应该有帮助。 对于防抖,我的理解就是“防止用户手抖”,所以使用场景就是本来用户只想点一次,但是由于手抖了 多点了几次,所以程序就不影响去响应那些本来不应该有的调用。

weixin_38434088的博客 506

防抖节流打包

防抖 function debounce(fn,delay){ let timer = null //借助闭包 return function() { if(timer){ clearTimeout(timer) } timer = setTimeout(fn,delay) // 简化写法 } } // 然后是旧代码 function showTop () { var scrollTop = d.

l_tsov的博客 821

深入理解防抖和节流

延迟 / 间隔时间需合理设置:输入搜索建议一般设 300-500ms,滚动监听设 100-200ms,具体根据业务场景调整。这两个技术主要解决频繁触发事件导致的性能问题,比如滚动事件、输入框搜索、按钮点击等场景。// 绑定this,确保函数内this指向正确(比如指向触发事件的元素)// 若当前时间 - 上次执行时间 >= 间隔时间,就执行函数。// 给window绑定节流事件,每100ms执行一次。// 重新设置定时器,延迟执行目标函数。// 给输入框绑定防抖事件,延迟500ms执行。

温故而知新 806

节流(throttling)和防抖(debouncing)

节流(throttling)和防抖(debouncing)是在处理用户输入和其他事件时常用的两种性能优化技巧。它们的主要目的是控制事件触发的频率,以避免不必要的重复操作,减轻系统负担,提高用户体验。

qq_41546003的博客 9085

基于Opencv+Mediapipe的头部姿态检测

在学生课堂专注度检测项目中,可以通过学生头部姿态来确定学生注意力方向,从而判断其是否专注于课堂。

weixin_67879842的博客 2335

从零理解Brep:用Python玩转3D建模的边界表示法(附OpenCASCADE示例)

本文深入解析了边界表示法(Brep)在3D建模中的应用,通过Python和OpenCASCADE的实战示例,详细介绍了Brep的核心数据结构、布尔运算、网格转换及3D打印优化技巧。适合CAD设计、3D打印和计算机图形学领域的开发者学习与实践。

n4o5p6q7r的博客 426

js防抖和节流理解及区别

保持对代码的热爱,并保存怀疑态度 在说防抖和节流之前我们先说一下闭包 什么是闭包? 通过作用域的嵌套,触发计算机的垃圾回收机制(硬盘),将原本的局部变量进化成私有变量的环境,叫闭包 function fn(){ var a = 10; return function(){ a ++ ; console.log(a); } } var f = fn(); f(); 什么是防抖? 首先先看一个例子

dergfg的博客 1202

Nvidia Tesla A100 驱动安装方法

Nvidia Tesla A100 驱动安装方法 遇到的问题:以前安装tesla系列、geforce系列等gpu 驱动的时候,只需执行nvidiaxxxx.run驱动包或者安装nvidiaxxxx.rpm包即可,但遇到新的GPU Nvidia Tesla A100的时候,安装完驱动似乎不起作用,找了半天资料,原来需要以下步骤才可以使用;

qq_24343177的博客 2万+

防抖与节流的简单理解

通过一个例子来简单理解节流与防抖

LK_315的博客 769

后仿真中《SDF反标必懂连载篇》之 Negative Delay (理论篇)

今天,学习一下SDF文件中的负数延时问题。比如下面的图片中的SETUPHOLD 中的hold time 为负数。

那么菜的博客 2573

面向红外小目标检测的SCTransNet:模型优势解析、代码实现与完整复现指南

摘要:本文详细介绍了基于SCTransNet的红外小目标检测全流程实践方案。针对红外小目标检测面临的三大挑战(特征稀缺、背景干扰、尺度变化),SCTransNet通过空-通道交叉注意力机制有效增强目标特征。文章包含完整的PyTorch实现代码,涵盖特征提取、注意力模块、多尺度融合等核心组件,并提供模型训练、评估的具体方法。同时给出毕设创新方向的建议,如模型轻量化、多模态融合等,帮助提升研究深度。该方案技术难度适中,应用价值明确,是红外目标检测领域理想的毕设选题方向。

m0_71589036的博客 4759

一文理解防抖与节流

防抖与节流是前端面试的重难考点。希望在这篇博客我能把这两个概念讲清楚。当事件触发后,延迟几秒后再执行回调。如果在这n秒内事件又被触发,则重新计时,是不是会清晰许多。频繁触发,只触发一次综合上述实例,我们在玩游戏时英雄会有一定的技能冷却时间,从而减少了一段时间内事件的触发频率,而节流的理解则是减少事件的触发频率,有选择性执行一部分事件。这里先再次重复一下两者定义:防抖: 当事件触发后,延迟n秒后再执行回调,如果在这n秒内时间再次被触发,则重新计时。...

zxdznyy的博客 1469

基于Linux的PCIe设备驱动开发入门到精通-- 11.2 锁机制与并发控制 (自旋锁、互斥锁) 11.3 性能瓶颈分析与优化建议

本文探讨Linux驱动开发中的性能优化方法论,重点聚焦并发控制与性能瓶颈分析。从锁机制选择(自旋锁、互斥锁等)到工具使用(ftrace、perf),详细介绍了定位锁竞争和CPU热点的实战步骤,包括ftrace事件跟踪和perf火焰图分析。针对常见性能瓶颈(CPU/内存/I/O/锁竞争),提出了锁粒度优化、无锁结构替换、中断处理优化等解决方案。强调性能优化需要理论结合实践,通过"假设-测量-验证"的循环持续迭代。为开发者提供了一套从问题定位到解决的完整方法论,助力开发高性能工业级驱动。

MHD0815的博客 127

手写防抖节流&防抖节流的理解

防抖和节流都是性能优化的一种手段,减少高频事件的触发。防抖就是持续触发(事件)不执行,不触发的一段时间后才执行;节流就是持续触发也执行,只不过执行的频率变低了

m0_68331234的博客 316

图文教程本地部署开源扣子Coze Studio工作流并接入 Gemini 大模型(windows亲测) Coze Studio 本地部署、Gemini 模型接入、开源 AI 工具平台、大模型工作流搭建

本文介绍了在Windows系统本地部署开源AI工具平台Coze Studio并接入Google Gemini大模型的完整教程。主要内容包括:1) 环境准备要求(Docker等);2) 获取源码和配置Gemini模型(需API密钥);3) 通过Docker Compose部署服务;4) 浏览器访问验证。文章指出该平台适合私有化部署,支持智能体和工作流搭建,但也存在插件系统不完善等局限。最后提供了相关资源链接,为开发者实现本地AI解决方案提供了实用指南。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2780

【离线OCR】微信离线实现图片OCR文本和表格识别

基于微信本地OCR引擎(由最新版微信自动安装)。通过Python对其官方调用逻辑进行完整翻译和封装,使开发者可以用简单的API调用其强大的OCR功能。

专注于医院数据分析技术与系统开发的创作与分享。 2623

理解一下防抖和节流

引言 防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 一. 防抖 1.1 防抖是啥 比如你写的input的onchange事件,用来搜索服务器的相关内容,每次改变一点input里的内容浏览器都会去服务器索要东西,其实浏览器想要的只是最终你输入的结果而已。防抖的目的就是想要你输入的最后一次结果。 1.2 手写防抖 1.2.1基础版 只要0.5秒之内没输入,就执行业务逻辑,执行完一次业务逻辑之后,时间计时器清空,从新开始。 let inp = document.querySelecter("in

少昊的博客 536

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

对防抖以及节流的理解

防抖:通过延迟触发函数,只在事件停止后执行一次函数,适用于需要等待用户操作完成后再执行的场景。节流:限制函数执行的频率,不论事件触发多少次,都会按照设定的时间间隔执行一次,适用于需要定期执行的高频事件。通过使用防抖和节流,可以显著提升应用的性能,避免因高频事件触发而造成的性能瓶颈。

qq_60535125的博客 819

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

如何理解防抖debounce和节流throttle

本人通过阅读网络上防抖和节流多篇相关的文章,并借鉴相关案例进行说明。 防抖 防抖就像人眨眼睛一样,不可能不停的眨,每隔一定时间眨一下,防止眼睛干涩,如果不停眨眼,别人以为你眼睛有毛病了。 再举一个例子,比如两个人对话,A不停的balabala(持续触发),如果A说话的时候有停顿,但是停顿的时间不够长,B就认为A还没说完,当A停顿时间超过足够长(一定间隔)就认为A说完了,然后B开始说(响应)。 节流...

flitrue的博客 571

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

javascript 对于防抖节流 理解

先介绍下 我的个人理解吧。 防抖:同一个事件短时间多次出发只会触发一次。 节流:每隔一段时间触发一次 最常用的大概就是搜索 窗口滚动 下面鼠标移动事件为例 <head> <meta charset="utf-8" /> <title></title> <style> div{ ...

weixin_43468902的博客 201

防抖和节流的理解

防抖(Debounce)和节流(Throttle)是前端开发中常用的两种优化技术,主要用于优化一些触发频率很高的事件(如窗口调整、鼠标移动、键盘输入、按钮触发等),以避免因事件频繁触发导致的性能问题。它们的核心区别在于对事件触发的处理方式不同。如果需要在事件完全停止触发后才执行处理函数,使用防抖。如果需要在事件频繁触发时控制执行频率,使用节流。在实际开发中,可以根据具体需求选择合适的优化方式,甚至可以结合使用防抖和节流来达到更好的效果。

m0_59501934的博客 6952

通俗理解防抖与节流函数

手写js防抖与节流函数 概念 防抖:顾名思义,防抖就是防止“抖动”,避免一个事件被多次触发。 就像大家在上网时难免会遇到网络不佳的时候,网页加载慢,而你心急的不断点击刷新按钮,在刷新进度条还为加载完成的时候,你又再次点击刷新,进度条又重新回到了起点,而最终加载出界面一定是在你最后一次点击刷新后,不再操作等待一定时间的结果。 虽然上面的例子并未用到防抖,但表现有相似之处。 若是假设每次刷新页面所用时间固定且相同,这样就和执行防抖操作有了相同的表现。 防抖函数: function debounce(fun,

weixin_46567428的博客 340

防抖与节流方案_如何理解js的防抖与节流

很高兴回答你这个问题,希望可以给你讲述清楚!我们先举个例子:项目有个需求是输入框在输入的时候进行搜索,展示下拉数据,但是没必要输入一个字都进行搜索,所以想到了在输入结束200毫秒后再进行搜索,从而引出来了 js的节流(throttle),防抖。什么是函数防抖和节流呢? 我们先来看下他们的概念函数防抖(debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时;典型的案例就...

weixin_39893728的博客 105

深刻理解防抖和节流

如何区分防抖与节流,看了就再也不会忘记

whisperSec的博客 243

关于节流和防抖的理解 简单举例

节流和防抖的理解

weixin_55092825的博客 4628
上一篇: 像特斯拉CEO马斯克一样,快速生成mock克隆数据
下一篇: 浅谈业务中台前端设计
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值