这是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的原创文章,尽在:"汪子熙":