一、什么是防抖和节流

Ps: 比如搜索框,用户在输入的时候使用change事件去调用搜索,如果用户每一次输入都去搜索的话,那得消耗多大的服务器资源,即使你的服务器资源很强大,也不带这么玩的。

1. 防抖 - debounce

其中一种解决方案就是每次用户停止输入后,延迟超过500ms时,才去搜索此时的String,这就是防抖。

  • 原理:将若干个函数调用合成为一次,并在给定时间过去之后仅被调用一次。
  • 代码实现:
function debounce(fn, delay) {
// 维护一个 timer,用来记录当前执行函数状态
let timer = null; return function() {
// 通过 ‘this’ 和 ‘arguments’ 获取函数的作用域和变量
let context = this;
let args = arguments;
// 清理掉正在执行的函数,并重新执行
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
}
}
let flag = 0; // 记录当前函数调用次数
// 当用户滚动时被调用的函数
function foo() {
flag++;
console.log('Number of calls: %d', flag);
} // 在 debounce 中包装我们的函数,过 2 秒触发一次
document.body.addEventListener('scroll', debounce(foo, 2000));
  1. debounce函数封装后,返回内部函数
  2. 每一次事件被触发,都会清除当前的timer然后重新设置超时并调用。这会导致每一次高频事件都会取消前一次的超时调用,导致事件处理程序不能被触发
  3. 只有当高频事件停止,最后一次事件触发的超时调用才能在delay时间后执行

2. 节流 - throttle

另一种解决方案比 防抖 要宽松些,这时我们不想用户一味的输入,而是给用户一些搜索提示,所以在当中限制每过500ms就查询一次此时的String,这就是节流。

  • 原理:节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。
  • 代码实现有两种,一种是时间戳,另一种是定时器

    1)时间戳实现:
function throttle(func, delay){
let prev = Date.now();
return function(){
const context = this;
const args = arguments;
const now = Date.now();
if(now - prev >= delay){
func.apply(context, args);
prev = Date.now();
}
}
}

当高频事件触发时,第一次应该会立即执行(给事件绑定函数与真正触发事件的间隔如果大于delay的话),而后再怎么频繁触发事件,也都是会每delay秒才执行一次。而当最后一次事件触发完毕后,事件也不会再被执行了。

2)定时器实现:

当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行;直到delay秒后,定时器执行执行函数,清空定时器,这样就可以设置下个定时器。

fucntion throttle(func, delay){
let timer = null; return funtion(){
let context = this;
let args = arguments;
if(!timer){
timer = setTimeout(function(){
func.apply(context, args);
timer = null;
}, delay);
}
}
}

当第一次触发事件时,肯定不会立即执行函数,而是在delay秒后才执行。

之后连续不断触发事件,也会每delay秒执行一次。

当最后一次停止触发后,由于定时器的delay延迟,可能还会执行一次函数。

3)综合使用时间戳与定时器,完成一个事件触发时立即执行,触发完毕还能执行一次的节流函数

function throttle(func, delay){
let timer = null;
let startTime = Date.now(); return function(){
let curTime = Date.now();
let remaining = delay - (curTime - startTime);
const context = this;
const args = arguments; clearTimeout(timer);
if(remaining <= 0){
func.apply(context,args);
startTime = Date.now();
}else{
timer = setTimeout(func, remaining);
}
}
}

需要在每个delay时间中一定会执行一次函数,因此在节流函数内部使用开始时间、当前时间与delay来计算remaining,当remaining <= 0时表示该执行函数了,如果还没到时间的话就设定在remaining时间后再触发。当然在remaining这段时间中如果又一次发生事件,那么会取消当前的计时器,并重新计算一个remaining来判断当前状态。

JS简单实现防抖和节流的更多相关文章

  1. JS中的防抖与节流

    什么是防抖?and什么是节流?一起来开心的学习下吧. 首先什么是防抖:就是在一定的时间内事件只发生一次,比如你点击button按钮,1秒内任你单身30年手速点击无数次,他也还是只触发一次.举个例子,当 ...

  2. Js中的防抖与节流函数

    1.何为防抖与节流函数呢? 1.防抖(debounce):通过setTimeout方式,在一定的时间间隔内,将多次触发的事件转化为一次触发.也就是说当一个用户一直触发这个函数,且每次触发函数的间隔小于 ...

  3. JS中的防抖和节流

    JS-防抖和节流 在进行窗口的resize.scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕.此时我们可以采用debounce(防抖)和 ...

  4. JS防抖和节流:原来如此简单

    一.函数防抖 前端开发工作中,我们经常在一个事件发生后执行某个操作,比如鼠标移动时打印一些东西: window.addEventListener("mousemove", ()=& ...

  5. js高阶函数应用—函数防抖和节流

    高阶函数指的是至少满足下列两个条件之一的函数: 1. 函数可以作为参数被传递:2.函数可以作为返回值输出: javaScript中的函数显然具备高级函数的特征,这使得函数运用更灵活,作为学习js必定会 ...

  6. 2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

    Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 ...

  7. 因为它,我差点删库跑路:js防抖与节流

    前言 前端踩雷:短时间内重复提交导致数据重复. 对于前端大佬来说,防抖和节流的技术应用都是基本操作.对于"兼职"前端开发的来说,这些都是需要躺平的坑. 我们今天就来盘一盘js防抖与 ...

  8. 面试必问题:JS防抖与节流

    摘要:防抖与节流可谓是面试常见,其实很好理解,下面带你分分钟了解防抖与节流的基本思想与写法~ 本文分享自华为云社区<JS防抖与节流快速了解与应用>,作者:北极光之夜. . 一.速识防抖: ...

  9. js防抖和节流

    今天在网上看到的,里面的内容非常多.说下我自己的理解. 所谓的防抖就是利用延时器来使你的最后一次操作执行.而节流是利用时间差的办法,每一段时间执行一次.下面是我的代码: 这段代码是右侧的小滑块跟随页面 ...

随机推荐

  1. C++笔试题库之编程、问答题 300~305道

    301. 以下代码有什么问题? cout << (true?1:”1″) << endl; 答:三元表达式“?:”问号后面的两个操作数必须为同一类型. 302.以下代码能够编译 ...

  2. poj 2406 Power Strings【kmp】

    kmp,根据next数组的性质如果有答案的话就是n/(n-(ne[n]+1)),否则是1 搬来打算用SA后来发现必须用DC3就没写 #include<iostream> #include& ...

  3. 图论之最短路算法之SPFA算法

    SPFA(Shortest Path Faster Algorithm)算法,是一种求最短路的算法. SPFA的思路及写法和BFS有相同的地方,我就举一道例题(洛谷--P3371 [模板]单源最短路径 ...

  4. Luogu P1069细胞分裂【分解质因数/数论】By cellur925

    题目传送门 发现这题真的坑超多啊...调了一晚上终于过了...我好菜啊qwq. 题意说的比较明白,让你求满足(si^k)%(m1^m2)==0的最小k值.然后看数据范围我们知道,我们肯定不能暴力的判断 ...

  5. Windows API 搭建OpenGL窗口

    步骤: 1.创建windows窗口,得到窗口句柄hwnd 2.获取该窗口的设备环境hDC(当然也可以获取其他的设备环境,但我们一般是在创建的窗口上绘制) 3.创建OpenGL绘制环境RC,这个只能从h ...

  6. Nginx系列篇二:linux搭建Nginx负载均衡

    建议先搭建好Nginx环境 可阅读--->Linux中搭建Nginx 1.准备好三台服务器[标配] 一.nginx负载均衡服务器:192.168.102.110,配置好Nginx 二.tomca ...

  7. 地址重用REUSEADDR

    一个socket连接断开后会进入TIME_WAIT,大概有几十秒,这个时候端口是无法使用的,如果不设定地址重用,就会报错,说端口占用. 创建一个socket实例后,在对这个实例进行地址绑定前,要设定地 ...

  8. 使用callabestatement接口调用存储过程

  9. Spark MLlib编程API入门系列之特征选择之向量选择(VectorSlicer)

    不多说,直接上干货! 特征选择里,常见的有:VectorSlicer(向量选择) RFormula(R模型公式) ChiSqSelector(卡方特征选择). VectorSlicer用于从原来的特征 ...

  10. 合理设置apache的连接数及进程工作方式

    网站在线人数增多,访问时很慢.初步认为是服务器资源不足了,但经反复测试,一旦连接上,不断点击同一个页面上不同的链接,都能迅速打开,这种现象就是说明apache最大连接数已经满了,新的访客只能排队等待有 ...