这是Jerry 2021年的第 11 篇文章,也是汪子熙公众号总共第 282 篇原创文章。

Jerry之前的文章 SAP UI5 OData谣言粉碎机:极短时间内发送两个Odata request, 前一个会自动被cancel掉吗,介绍过SAP成都研究院CRM Fiori开发团队开发过的一个Live Search的场景。

用户创建Opportunity,维护Account字段,每输入一个字符,都会触发SAP UI5 Input控件的liveChange事件。在该事件的onAccountInputFieldChanged处理函数里,根据用户输入,发送OData请求到后台进行查询。

如果用户输入速度很快,则在短时间内,会有多个OData请求发送到后台,进而出现Jerry文章里描述的OData请求被cancel的情况。

最近Jerry做SAP Spartacus开发,遇到了同样的场景。因此通过本文把自己最近所学总结一下,记录下SAP UI5和Angular里如何使用函数防抖(Debounce)和函数节流(Throttle)来避免短时间内触发高频次函数调用的情况出现。

为了便于讲解,Jerry做了一个只包含一个Input控件的SAP UI5页面。源代码地址.

在Input里输入字符,会触发liveChange事件,将当前Input的最新内容,发送到一个我自己开发的后台服务去。该后台服务什么也不做,只是简单将收到的内容返回给UI.

这个SAP UI5页面里的Input控件的liveChange事件处理如下:

从Chrome控制台打印的输出来看,我在一秒钟之内,连续快速输入了1234共4个字符,一共产生了4个发送往后台的请求。

SAP UI5如何使用函数防抖(Debounce)来降低函数调用的频次

函数防抖(Debounce),最早源于机械开关和继电器的术语“去弹跳”,即将多个信号合并为一个信号。

想象一个大家现实生活中都会遇到的场景:进电梯。电梯都有一个自动关闭门的超时时间,假设为2秒。当电梯检测到有人进入时,会重置这个2秒的计时器。如果下一个2秒之内,没有新的乘客进入电梯,电梯门才会自动关上。

电梯延迟关门这个场景,就是一个典型的函数防抖的现实例子。电梯关门的行为就是“函数”,通过电梯门的自动关闭超时时间,2秒,来延迟电梯门的关闭动作的执行,从而降低电梯门的关闭频率,这就是“防抖”。

可以想象,如果电梯门的自动关闭没有设定超时时间,而是检测到没有人进出之后,立即关闭,这样会大大增加电梯门开合的频率,既浪费能源,也不安全。这就好比Jerry本文开头提到的例子:既然我短时间内输入了字符1234,我期望在UI看到的,是后台服务接收到1234后返回的结果。至于后台如何对前三个请求,即字符1,字符12和字符123进行处理,我不再关心。

我们可以仿照电梯门关闭超时时间的设定,来给SAP UI5的函数调用实现防抖控制。

下图debounce变量是一个函数构造器,本身是一个函数,接收另一个函数fn作为输入参数,职责是通过闭包,将fn改造成一个具有防抖控制功能的新函数,该新函数通过第17行的return语句返回。

防抖时间间隔通过函数构造器另一个输入参数delay指定。

假设我们指定的防抖时间间隔为3000毫秒即3秒,如果3秒之内,debounce函数构造器返回的新函数被不断调用,此时执行上图代码第19行,调用clearTimeout重置计数器,此时原始函数fn不会得到执行。这个场景可以类比成:在电梯关门超时时间内,又有新的乘客进入,电梯超时计时器重置,电梯门不会关闭。

代码第20行,使用setTimeout重启超时时间间隔为3秒的计数器,3秒过后,如果JavaScript任务队列里没有其他待执行任务,则执行原始函数fn. 代码的第20行,好比电梯设备重新开启了3秒的超时定时器。

如果在等待的3秒之内,没有新的函数调用触发,则3秒过后,执行21行的原始函数fn;这好比电梯在3秒之内,始终没有新的乘客进入,则 3秒过后,电梯门自动关闭。

debounce函数构造器的使用方式也很简单。

代码第78行,将原始的sendRequest函数,以及3000毫秒的防抖时间间隔,传入debounce构造器,返回一个兼有数据发送功能和防抖功能的debounceVersion函数。在第85行原来调用sendRequest函数的位置,改为调用debounceVersion函数即可。

函数防抖功能的测试:我在同一分钟的第46秒,48秒,50秒,51秒四个时间点,分别输入了1,2,3,4总共4个字符,但是在最后一次即51.996秒又过了3秒之后,才仅仅有一个请求发送到后台:这说明3秒的函数防抖间隔生效了:

SAP UI5如何使用函数节流(Throttle)来降低函数调用的频次

上述函数防抖的实现存在一个问题,还是以电梯的例子来说明。

设想有一个空间无限的电梯,关门的超时时间为3秒。如果不断的有新的乘客以小于3秒的时间间隔进入电梯,则电梯门永远没有机会关闭——即函数永远得不到执行。

函数节流(Throttle)是另一种降低函数调用频次的思路,同函数防抖的区别是,后者能保证在指定的节流间隔内,至少执行一次函数。

函数节流构造器的一个最简单的实现版本:

被节流器改造后的函数每次触发时,取一个当前系统时间戳,同前一次触发时取的时间戳比较。如果二者的时间差,大于等于构造器的输入参数delay即节流时间间隔,则进入第39行的else分支,触发原始函数fn;否则说明节流时间间隔还未到达,使用第34行setTimeout,将原始函数fn,重新放入JavaScript事件队列内,延迟执行:

函数节流版本的构造器使用方式,同函数防抖版本的构造器没有差别:将原始函数sendRequest传入构造器throttle,返回一个具有节流功能的新函数throttleVersion,在Input控件liveChange事件处理函数里,调用throttleVersion这个新函数即可。

函数节流的测试结果:我设置的节流时间间隔为3秒,从Chrome控制台打印输出能观察到,SAP UI5确实是大致以3秒的时间间隔,向后台发起的数据请求。

本文介绍的两种函数防抖和函数节流的实现代码,仅仅考虑了最基本的情况,还有很多不完善的地方,有兴趣的朋友可以在网络上搜索,这方面的资料非常多,这里不再赘述。

Jerry之前的分享提到过,Angular是响应式编程开发库RxJS的重度使用者,后者提供了众多功能强大的Operators,使得Angular开发人员不用重复造轮子,就能轻易实现出具有函数防抖和函数节流的场景。

用Angular重新实现本文SAP UI5的Demo,总共代码只有44行:

从rxjs/operators工具库中直接导出debounceTime和throttleTime这两个operators:

类似SAP UI5 Input控件的liveChange,Angular FormControl的valueChanges也给应用开发人员提供了编写业务逻辑,响应用户输入的位置:后者的valueChanges数据类型是Observable,应用开发人员可以通过pipe调用,传入RxJS各种功能强大的Operators,让自己编写的包含业务逻辑的事件响应函数,按照实际需求来触发。

比如上图第39行代码,语义是:绑定到jerryFormControl的input控件有valueChanges发生时,首先经过防抖器的处理。至于是否能够满足触发valueChanges对应的事件处理函数的条件,由防抖器debounceTime的内部处理逻辑决定。

RxJS防抖器debounceTime的内部实现使用了setInterval,逻辑比Jerry本文介绍的debounce函数构造器复杂得多了,通过这些调用栈就能感受一二:

Jerry这个Angular Demo的函数节流(时间间隔设定为2秒)功能测试如下:我在7秒之内,匀速输入1234567890abc,可以看到总共触发了三个发送到后台的请求,请求间隔为2秒:

希望本文能帮助大家对函数防抖和函数节流的概念有一个最粗浅的理解,感谢阅读。


更多阅读

(0) SAP UI5应用开发人员了解UI5框架代码的意义

(1) SAP UI5 module懒加载机制

(2) SAP UI5 控件渲染机制

(3) HTML原生事件 VS SAP UI5 Semantic事件

(4) SAP UI5控件元数据的元数据实现

(5) SAP UI5控件的实例数据修改和读取逻辑

(6) SAP UI5控件数据绑定的实现原理

(7) SAP UI5控件数据绑定的三种模式:One Way, Two Way和OneTime实现原理比较

(8) SAP UI5控件ID的生成逻辑

(9) SAP UI5控件的多语言(国际化,Internationalization,i18n)支持的实现原理

(10) XML视图里的button控件

(11) button控件和它背后的DOM元素

(12) SAP UI5 OData谣言粉碎机:极短时间内发送两个Odata request,前一个会自动被cancel掉吗

(13) 漫谈SAP产品里页面上的Checkbox设计与实现系列之一

更多Jerry的原创文章,尽在:“汪子熙”:

SAP UI5和Angular的函数防抖(Debounce)和函数节流(Throttle)实现原理介绍相关推荐

  1. 函数防抖Debounce和函数节流Throttle

    函数节流 & 函数防抖 函数节流和函数防抖 函数节流和函数防抖二者很容易被混淆起来.下面贴英文原文,建议认真阅读: Debouncing enforces that a function no ...

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

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

  3. 函数防抖debounce和节流throttle

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

  4. SAP UI5和angular里的常量定义

    SAP UI5 以我们以前负责的Opportunity为例,直接创建一个新的js文件,然后用所有字段为大写格式的JSON对象来模拟constant.UI5 framework也是用的这种方式. Ang ...

  5. 如何使用原生的 JavaScript 代码,触发 SAP UI5 按钮控件的点击事件处理函数

    我的技术交流群里,有朋友提问: 我有个 UI5 按钮,想用原生 js 去触发 click 事件.在 dom 上检测到 click 已经触发了,但是按按钮的动作响应没有发生.请问如何解决,谢谢. 解决这 ...

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

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

  7. 详解防抖函数(debounce)和节流函数(throttle)

    函数防抖(debounce) 函数防抖,就是指触发事件后,在 n 秒后只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数的执行时间. 简单的说,当一个动作连续触发,只执行最后一次. 列举: ...

  8. 函数防抖 和 函数节流

    函数防抖 和 函数节流 函数防抖(debounce) 概念 函数防抖 就是指 触发事件后 在 n 秒内 函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间. 简单的说,当一个动作 ...

  9. 深入学习SAP UI5框架代码系列之八:谈谈 SAP UI5 的视图控件 ID,以及 SAP UI5 视图和 Angular 视图的异同

    今天是 2021 年 4 月 27 日,周二,SAP 全球心理健康日.SAP 全球的员工,今天放假一天. 这不,早在上周五,我所在的 SAP Spartacus 开发团队的开发经理,就贴心地在 Sla ...

最新文章

  1. 18段代码带你玩转18个机器学习必备交互工具
  2. 相机居然能存储气味,未来智能家居会是什么样? | CCF C³
  3. window python输入路径问题--转义字符
  4. 关于PR转PO的注意事项
  5. D - Yet Another Problem On a Subsequence CodeForces - 1000D (DP,组合数学)
  6. Java孩子父母类_父母和子女复选框
  7. contentprovider的学习实例总结
  8. 【读fastclick源码有感】彻底解决tap“点透”,提升移动端点击响应速度
  9. 计算机楼综合布线设计图,现代综合大楼综合布线设计方案
  10. 毕节市搜索引擎优化_毕节市网站建设58同城
  11. 如何购买腾讯云学生服务器
  12. rank函数在c语言怎么用,如何利用RANK函数排名?RANK函数怎么使用?
  13. 做头条问答项目,月入4000元到底有多简单
  14. leetcode——回溯
  15. mixin(公共样式定义)
  16. Win7,CentOS 6.4双系统 硬盘安装
  17. DDR设计之地址和容量计算、Bank理解
  18. netstat 中state详解
  19. 多线程相关实例(多线程经典应用场景)
  20. 不要把学习技术当做任务、攀比和终极目标。 [IT傻博士原创]

热门文章

  1. keepalived+haproxy(双主)+nginx(静态)+lamp(动态)部署phpBB
  2. 大数据泄露你的行踪?隐私不再是隐私
  3. 《社交网站界面设计(原书第2版)》——2.11 提问
  4. win7/WIN8.1(x64) 下使用MSDE WIN10不行
  5. angularjs 弹出框 $modal传值
  6. centos7.3部署kvm虚拟化
  7. 面向对象程序设计第二次作业(2)
  8. Tomcat配置优化
  9. Solaris、Mac OS系统日志分析工具
  10. 寻找一个字符串中的最长不重复子串的长度