Throttle

在现代浏览器中,帧速率为60fps是流畅性能的目标,给定我们16.7ms的时间预算用于响应一些事件所有需要的更新。这样可以推断,如果每秒发生n个事件并且回调执行,需要t秒的时间,为了流畅运行,

1 / n >= t

如果t以毫秒为单位,

1000 / n >= t

如果你曾经使用mousemove事件,你会知道产生mousemove事件的数量每秒可以超过60次。如果我们的回调需要超过16.7ms,那就开始凌乱了。

  1. var then = 0;
  2. function log() {
  3. var now = Date.now();
  4. if (1000 / (now - then) > 60) {
  5. console.log('It\'s over 9000!!!');
  6. }
  7. then = now;
  8. }
  9. window.onmousemove = log;

实现

Throttle 允许我们限制我们激活响应的数量。我们可以限制每秒回调的数量。反过来,也就是说在激活下一个回调之前要等待多少时间;

  1. var delta = 1000;
  2. var then = 0;
  3. function log() {
  4. console.log('foo');
  5. }
  6. function throttledLog() {
  7. var now = Date.now();
  8. if (now - then >= delta) {
  9. log();
  10. then = now;
  11. }
  12. };
  13. window.onmousemove = throttledLog;

我们可以用 fps替换delta,并推断出不同的代码。

  1. var fps = 60;
  2. ...
  3. function throttledLog() {
  4. var now = Date.now();
  5. if (1000 / (now - then) < = fps) {
  6. log();
  7. then = now;
  8. }
  9. };
  10. window.onmousemove = throttledLog;

我们也可以通过使用setTimeout来实现相同的结果。 但是,不是检查时间差,而是检查状态变化。

第一次,我们可以安全地激活回调。一旦完成,只有在等待 delta 时间之后才能再次激活回调。

  1. var delta = 1000;
  2. var safe = true;
  3. function log() {
  4. console.log('foo');
  5. }
  6. function throttledLog() {
  7. if (safe) {
  8. log();
  9. safe = false;
  10. setTimeout(function() {
  11. safe = true;
  12. }, delta);
  13. }
  14. };
  15. window.onmousemove = throttledLog;

Debounce

这个术语-去抖动 来自电子学的领域,手动开关输入的信号被发送到数字电路中。在电子学中,当你按一个物理按钮一次,数字电路可能读到多个按压,因为按钮的物理属性(金属触点,弹簧,磨损件等)。

去抖动意味着采集到的所有这些波动的信号,并把它们当作一个。

例子

一个简单的例子已经存在于JS中:keydown vs keyup。假设您正在处理一个项目,并且需要输入内容。但是你想要每次敲击键盘得到一个字符。输入时,如果长按一个键,keydown事件将连续被触发,但是 keyup 事件只有在按键被释放时才会触发。

  1. window.onkeyup = function() {
  2. console.log('onkeyup');
  3. }
  4. window.onkeydown = function() {
  5. console.log('onkeydown');
  6. }

这种行为上的差异对于确定输入是否已完成是有用的。在示例场景中,它是你将使用的keyup事件。在某种程度上,我们可以说keydown 是原始输入,keyup 是去抖动输入。

实现

当事件发生时,我们不会立即激活回调。相反,我们等待一定的时间并检查相同的事件是否再次触发。如果是,我们重置定时器,并再次等待。如果在等待期间没有发生相同的事件,我们就立即激活回调。

  1. var delta = 1000;
  2. var timeoutID = null;
  3. function log() {
  4. console.log('foo');
  5. }
  6. function debouncedLog() {
  7. clearTimeout(timeoutID); // reset timer
  8. timeoutID = setTimeout(function() {
  9. // wait for some time
  10. // and check if event happens again
  11. log();
  12. }, delta);
  13. };
  14. window.onkeydown = debouncedLog;

Immediate

Immediate是Debounce的精确版本。比起 Debounce 的 等待后续事件触发,然后再激活回调,Immediate 是 立即激活回调,然后等待后续事件在一定时间内触发。

实现

就像Throttle的情况一样,我们需要一个状态变量来检查是否应该激活我们的回调。我们在Debounce不需要一个,因为timeoutID隐式管理这部分。

  1. var delta = 1000;
  2. var timeoutID = null;
  3. var safe = true;
  4. function log() {
  5. console.log('foo');
  6. }
  7. function immediatedLog() {
  8. if (safe) {
  9. log();
  10. safe = false;
  11. }
  12. clearTimeout(timeoutID);
  13. timeoutID = setTimeout(function() {
  14. safe = true;
  15. }, delta);
  16. };
  17. window.onkeydown = immediatedLog;
  18. //转载至 http://www.css88.com/archives/6589

JavaScript中的定时控制-Throttle、Debounce、Immediate的基本概念相关推荐

  1. 如何在JavaScript中使用apply(?),call(?)和bind(➰)方法

    by Ashay Mandwarya ?️?? 由Ashay Mandwarya提供吗? 如何在JavaScript中使用apply(?),call(?)和bind(➰)方法 (How to use ...

  2. javascript中的对象之间继承关系

    相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象 ...

  3. JavaScript中的定时器详解

    前言 JavaScript 中有两种定时器: setTimeout():指定时间后执行一段代码(延迟执行). setInterval():每隔一段时间执行一段代码(间隔执行). 下面单独对两种计时器进 ...

  4. 【译】JavaScript 中的节流(throttle)和防抖(debounce)

    目录 JavaScript中的节流和防抖 节流和防抖的区别 使用场景 实现节流和防抖 防抖 节流 JavaScript中的节流和防抖 你是否因过度调用函数而影响性能呢? 解决性能问题是在 JavaSc ...

  5. keras 香草编码器_完善纯香草javascript中的拖放

    keras 香草编码器 Drag-and-drop functionality is the bread and butter of a modern web UX. It's an aspect o ...

  6. throttle/debounce应用及原理

    文章目录 基础应用 "时间"防抖 "空间"防抖 进阶应用 throttleFirst throttleLast throttleLatest debounce ...

  7. JavaScript中的一等公民: 函数(Function)

    1. 函数的基本使用 使用函数声明或者函数表达式创建一个函数 foo(); //foo bar(); //Uncaught ReferenceError: Cannot access 'bar' be ...

  8. 浅析 JavaScript 中的 函数 uncurrying 反柯里化

    柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...

  9. JavaScript中,this的绑定规则

    对于 JavaScript 新手来说,this 是非常基础同时也难以理解的知识点. 比如下面的代码,this 指向就有三种方式. 在<你不知道的 JavaScript>一书中,我总算比较清 ...

最新文章

  1. grep, sed, awk
  2. Python 下载的九种方法
  3. Python——pip批量安装和卸载package
  4. 爱拉托逊斯方法以及素数判断
  5. luogu P2241 统计方形
  6. 元件原理图旋转45度_大口径大曲率半径光学元件的高精度检测
  7. initramfs 工作原理
  8. python制作会动的表情包_Python自动生成表情包,python在手,从此斗图无敌手
  9. Git工作笔记001---Windows下安装Git Core以及TortoiseGit安装与配置
  10. 事件库之Redis自己的事件模型-ae
  11. 组策略下发URL地址时的问题
  12. 编译OpenJDK12:globalDefinitions_visCPP.hpp(46): fatal error C1083:inttypes.h No such file or directory
  13. php中in array函数_PHP函数in_array()使用详解
  14. 史上最全介绍--新能源汽车整车控制器VCU开发流程功能概述
  15. BZZ节点如何成为有效节点,BZZ节点优势
  16. html所有的标签,html所有标签超详细概述
  17. 【一文带你读懂机器学习】线性回归原理
  18. excel表格汇总数据
  19. android MediaCodec 音频编解码的实现——转码
  20. 盘点HR日常工作数据计算大全

热门文章

  1. Google 推出的 web 输入法工具 Google input tools
  2. 用python检测电脑IP地址是否发生变化并提醒自己
  3. 搜索不到蓝牙鼠标问题的分析
  4. SGU 103 Traffic Lights(最短路)
  5. 运营商业务及网络介绍
  6. 从Matlab的 .fig 图窗文件中提取相关数据
  7. packet tracer 4321路由器加光纤口
  8. GPhone使用技巧
  9. 2021-8-25【PTA】【九连环问题】
  10. matlab学习(4)