这是Jerry 2021年的第 9 篇文章,也是汪子熙公众号总共第 280 篇原创文章。
本文Jerry本来写于2016年5月,过后公布于团队外部wiki.
五年过后,Jerry应用的开发框架,从SAP UI5变成了Angular.
最近Jerry在做SAP Spartacus开发时,遇到了和本文形容极为相似的场景。因为我学习新常识的时候,总喜爱把之前曾经相熟的常识拿来做横向类比,所以本文首先重温一个不少SAP UI5开发人员都了解得似是而非的知识点,为后续的分享做一个铺垫。
本公众号后续的文章,会介绍如何在Angular技术栈里,应用RxJS优雅地解决此类问题。
RxJS是Jerry之前的文章 Jerry在2020 SAP寰球技术大会的分享:SAP Spartacus技术介绍的文字版 已经提到的,一个Angular重度依赖的基于Observables的响应式编程库。
本文余下的局部,咱们从新回到SAP UI5的世界。
My Opportunities是SAP成都研究院CRM Fiori开发团队于2014年到2016年之间,负责的CRM Fiori利用之一。用户在创立Opportunity时,须要指定Account字段,该字段反对Live Search性能,比方敲入一个字符"J", UI5会发送一个OData申请到后盾,后者异步返回Account模型里fullname字段蕴含J的那些数据,作为搜寻后果,通过下拉列表的形式显示在UI上:
OData申请url:
/sap/opu/odata/sap/CRM_OPPORTUNITY/AccountCollection?$top=10&$filter=substringof(%27J%27,fullName)&sap-client=001&$expand=MainAddress&$select=accountID,MainAddress/city,MainAddress/country,fullName
以此类推,如果在字符J前面再敲一个e,会触发一个新的OData申请,依据"Je"搜寻:
/sap/opu/odata/sap/CRM_OPPORTUNITY/AccountCollection?$top=10&$filter=substringof(%27Je%27,fullName)&sap-client=001&$expand=MainAddress&$select=accountID,MainAddress/city,MainAddress/country,fullName
过后组内有共事察看到一个景象:如果用户疾速输出一连串字符,则在Chrome开发者工具Network标签页里,从工夫程序上来说,先触发的OData申请,状态会被标注为canceled:
基于这个察看后果,有共事做出了这样的猜想:
极短时间内发送两个OData申请,则第一个会主动被cancel掉。
这个猜想即使纯正从字面意义上讲,也有两点值得斟酌之处:
(1) “极短时间”,多短算极短?1毫秒?1微秒?
(2) OData申请被谁cancel掉?UI5框架还是浏览器?
为了验证这个猜想是否正确,我写了一段简略的测试代码:在一个for循环里应用SAP UI5 OData Model read API,收回10个OData申请:
测试发现,无论是同步还是异步申请,都未呈现被cancel的状况。
10个同步申请的执行状况如下图所示:同Timeline序列栏能够看到,10个同步申请按工夫程序,被后盾解决,再顺次收到响应。
10个异步申请的执行状况:10个申请简直同时收回,同时收到响应。
测试结果表明,这个猜想“极短时间内发送两个OData申请,则第一个会主动被cancel掉”不成立。
然而咱们在Chrome开发者工具里,的确察看到有OData申请被cancel,这又如何解释呢?
首先应用Chrome开发者工具network标签页里的Initiator性能,找到这些被cancel的OData申请,是下图第523行的refresh办法触发的:
在refresh办法内,如果第600行的标记位bChangeDetected为true,那么执行第601行的abortPendingRequest:
所以,这是一个“相煎何太急”的场景:在应用SAP UI5 OData Model API发送OData申请时,如果满足条件(bChangeDetected = true),则OData API会终止(abort)前一个pending的申请。
abortPendingRequest的正文写道:如果开发人员能确信,以后申请的响应数据不再须要,则可调用该办法来停止该申请。回到本文结尾介绍的Opportunity Live Search的例子,当用户输出J,而后再输出e时,显然,前一个依据J进行搜寻的申请,曾经不再须要了,咱们仅仅须要将Je对应的申请发送到后盾即可。这就是abortPendingRequest办法调用的应用场景之一。
总共有多少种状况,会触发SAP UI5去调用abortPendingRequest办法?
依据关键字abortPendingRequest搜寻,失去下列三处地位,即OData Model的三个API办法:
filter
sort
refresh
Jerry之前SAP CRM开发团队的共事Ben(文章 SAP成都研究院李三郎:SCP Application Router简介 的作者),对这三个API做了进一步的钻研。
在SAP UI5的OData框架的ODataModel.js中,保护了一个HTTP申请的pending列表,其内保护了曾经发送,然而还没有收到响应的request对象:
SAP UI5每次发动OData申请时,都会调用ODataModel的_request()办法。该办法会把以后的request对象加到pending列表中,并通过一个wrap method包装回调函数,确保在响应返回时,首先把缓存的request对象从pending列表中拿掉:
每次应用OData Model API发动filter, sort和refresh操作时,SAP UI5都会查看pending列表中是否存在pending的request对象。若存在,则先abort掉它,这就是咱们在Chrome开发者工具里察看到的状态为canceled的HTTP申请。
总结
只有同时满足下列三个条件,咱们能力察看到SAP UI5收回的OData申请被cancel的状况。
(1) 同一个OData Model实例收回的间断申请,因为pending列表是保护在this级别上的。
(2) 某个申请发送时,存在前一个状态还处于pending的HTTP申请。
(3) SAP UI5应用程序通过OData Model API发动filter, sort或者refresh操作。
这也印证了本文开始Jerry在for循环里,间断调用OData Model的read API发送申请时,没有察看到呈现cancel的状况,因为不满足上述条件3.
当然,大前端倒退到明天,曾经有各种欠缺的理念和计划来防止此类问题。比方函数节流(throttle)和防抖(debounce)理念:
假如咱们把用户在Account字段的每一次输出事件,触发的事件处理函数的执行,用一根竖线示意。则未经任何解决的原始场景,用函数节流和函数防抖从新实现的场景,三者比拟的示意图如下:
从图中不难看出,利用了函数节流和防抖机制后,事件响应函数的触发频次大大降低。当事件响应函数自身蕴含了简单耗时的业务逻辑时,触发频次的升高意味着防止了大量不必要的执行开销。
Jerry后续的文章,会通过理论例子,来介绍SAP UI5如何实现函数节流和防抖,二者的区别,以及如何在Angular里用RxJS更优雅地实现这两种机制。感激浏览。
更多浏览
(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元素
更多Jerry的原创文章,尽在:"汪子熙":