SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎

i042416發表於2021-01-29

這是Jerry 2021年的第 9 篇文章,也是汪子熙公眾號總共第 280 篇原創文章。

本文Jerry原本寫於2016年5月,當時釋出於團隊內部wiki.


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


五年過後,Jerry使用的開發框架,從SAP UI5變成了Angular.

最近Jerry在做SAP Spartacus開發時,遇到了和本文描述極為類似的場景。因為我學習新知識的時候,總喜歡把之前已經熟悉的知識拿來做橫向類比,所以本文首先重溫一個不少SAP UI5開發人員都理解得似是而非的知識點,為後續的分享做一個鋪墊。

本公眾號後續的文章,會介紹如何在Angular技術棧裡,使用RxJS優雅地解決此類問題。

RxJS是Jerry之前的文章  Jerry在2020 SAP全球技術大會的分享:SAP Spartacus技術介紹的文字版 曾經提到的,一個Angular重度依賴的基於Observables的響應式程式設計庫。


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


本文餘下的部分,我們重新回到SAP UI5的世界。

My Opportunities是SAP成都研究院CRM Fiori開發團隊於2014年到2016年之間,負責的CRM Fiori應用之一。使用者在建立Opportunity時,需要指定Account欄位,該欄位支援Live Search功能,比如敲入一個字元"J", UI5會傳送一個OData請求到後臺,後者非同步返回Account模型裡fullname欄位包含J的那些資料,作為搜尋結果,透過下拉選單的方式顯示在UI上:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


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


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


當時組內有同事觀察到一個現象:如果使用者快速輸入一連串字元,則在Chrome開發者工具Network標籤頁裡,從時間順序上來說,先觸發的OData請求,狀態會被標註為canceled:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


基於這個觀察結果,有同事做出了這樣的猜測:

極短時間內傳送兩個OData請求,則第一個會自動被cancel掉。

這個猜測即便純粹從字面意義上講,也有兩點值得推敲之處:

(1) “極短時間”,多短算極短?1毫秒?1微秒?

(2) OData請求被誰cancel掉?UI5框架還是瀏覽器?

為了驗證這個猜測是否正確,我寫了一段簡單的測試程式碼:在一個for迴圈裡使用SAP UI5 OData Model read API,發出10個OData請求:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


測試發現,無論是同步還是非同步請求,都未出現被cancel的情況。

10個同步請求的執行情況如下圖所示:同Timeline序列欄可以看到,10個同步請求按時間順序,被後臺處理,再依次收到響應。


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


10個非同步請求的執行情況:10個請求幾乎同時發出,同時收到響應。


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


測試結果表明,這個猜測“極短時間內傳送兩個OData請求,則第一個會自動被cancel掉”不成立。

但是我們在Chrome開發者工具裡,確實觀察到有OData請求被cancel,這又如何解釋呢?

首先使用Chrome開發者工具network標籤頁裡的Initiator功能,找到這些被cancel的OData請求,是下圖第523行的refresh方法觸發的:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


在refresh方法內,如果第600行的標誌位bChangeDetected為true,那麼執行第601行的abortPendingRequest:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


所以,這是一個“相煎何太急”的場景:在使用SAP UI5 OData Model API傳送OData請求時,如果滿足條件(bChangeDetected = true),則OData API會終止(abort)前一個pending的請求。

abortPendingRequest的註釋寫道:如果開發人員能確信,當前請求的響應資料不再需要,則可呼叫該方法來中止該請求。回到本文開頭介紹的Opportunity Live Search的例子,當使用者輸入J,然後再輸入e時,顯然,前一個根據J進行搜尋的請求,已經不再需要了,我們僅僅需要將Je對應的請求傳送到後臺即可。這就是abortPendingRequest方法呼叫的使用場景之一。


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


總共有多少種情況,會觸發SAP UI5去呼叫abortPendingRequest方法?

根據關鍵字abortPendingRequest搜尋,得到下列三處位置,即OData Model的三個API方法:

filter sort refresh


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


Jerry之前SAP CRM開發團隊的同事Ben(文章  SAP成都研究院李三郎:SCP Application Router簡介 的作者),對這三個API做了進一步的研究。

在SAP UI5的OData框架的ODataModel.js中,維護了一個HTTP請求的pending列表,其內維護了已經傳送,但是還沒有收到響應的request物件:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


SAP UI5每次發起OData請求時,都會呼叫ODataModel的_request()方法。該方法會把當前的request物件加到pending列表中,並透過一個wrap method包裝回撥函式,確保在響應返回時,首先把快取的request物件從pending列表中拿掉:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


每次使用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.


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


當然,大前端發展到今天,已經有各種完善的理念和方案來避免此類問題。比如函式節流(throttle)和防抖(debounce)理念:

假設我們把使用者在Account欄位的每一次輸入事件,觸發的事件處理函式的執行,用一根豎線表示。則未經任何處理的原始場景,用函式節流和函式防抖重新實現的場景,三者比較的示意圖如下:


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


從圖中不難看出,應用了函式節流和防抖機制後,事件響應函式的觸發頻次大大降低。當事件響應函式本身包含了複雜耗時的業務邏輯時,觸發頻次的降低意味著避免了大量不必要的執行開銷。

Jerry後續的文章,會透過實際例子,來介紹SAP UI5如何實現函式節流和防抖,二者的區別,以及如何在Angular裡用RxJS更優雅地實現這兩種機制。感謝閱讀。


SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


更多閱讀

(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的原創文章,盡在:"汪子熙":

SAP UI5 謠言粉碎機:極短時間內傳送兩個Odata請求,前一個會自動被cancel掉嗎


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2754415/,如需轉載,請註明出處,否則將追究法律責任。

相關文章