有時咱們能在Chrome開發者工具的Network tab裏觀察到SAP UI5應用會發出某些狀態爲"取消"的OData請求。以下圖第五個請求。瀏覽器
以前有一種似是而非的說法:極短期內發送兩個OData請求,則第一個會自動被cancel掉。緩存
這個說法從字面上看,有兩點值得推敲:框架
1. cancel掉,被誰cancel掉?UI5框架仍是Chrome?異步
2. 「極短」,多短算極短?函數
我用代碼在for循環裏一共發10個OData請求:工具
不管是同步仍是異步,都沒有任何的請求被cancel。this
10個同步請求:代理
10個異步請求:對象
就算髮100個request都不會有一個request被cancel:開發
驗證結果,以前的說法「極短期內發送兩個OData request,前一個會自動被cancel掉」是錯誤的。
那再回到本文第一張圖觀察到的cancel的場景, 緣由到底是什麼?
觀察產生了被取消的OData請求的應用代碼,觀察到第523行有這個refresh操做:
在這個方法的第601行,bChangeDetected變量爲true致使abortPendingRequest的調用。
abortPendingRequest的註釋已經很清楚地說明問題了。
什麼狀況下會致使AbortPendingRequest? 直接使用Chrome開發者工具的全文搜索獲得答案:OData model的三個API: filter, sort, refresh
下面是個人同事Li Ben的進一步補充。
1. 在哪裏能夠看到這個cancel現象?
在咱們的live search功能上,若是輸入較快或者正常速度輸入,會看到前面不少輸入請求都會被cancel掉:
若是輸入較慢則不會:
真的是快慢的緣由嗎?
仔細觀察network發現,真正的緣由是當上一次的network還處於pending狀態的時候,繼續輸入發起的請求就會cancel掉上一次的請求:
繼續深究, 這是在哪裏作到的?
在SAP UI5的OData框架裏面有這樣的實現:
在ODataModel.js中維護了一個http request的pending list,將已經發送可是尚未收到響應的request對象都緩存在這個列表中:
每次發起OData請求的時候都會調用ODataModel的_request()方法,這個方法會把當前的request加到pending list中,而且經過一個wrap method包裝回調函數,確保在響應返回的時候首先把緩存的request對象從pending list中拿掉:
每次在OData Model上發起filter, sort, refresh操做的時候,都會檢查是否存在pending的request對象,若是存在未完成的請求,abort掉它:
回答上面的問題,在什麼狀況下會發生這種現象?
1. 同一個ODataModel的instance上發出的連續請求,由於pending list是緩存在this級別上面的。
2. 前一個Http請求的network還處於pending status的時候。
3. 就讀ODataModel的代碼和觀察到的現象,在ODataModel上發起filter, sort或者refresh的時候。
爲何在OData的request對象上發起abort調用就能夠取消底層的network call?
簡單的說,UI5裏面的OData Request對象是底層的Ajax Request對象XmlHttpRequest的一個代理,在ODataModel的_submit方法中:
具體實現是UI5中利用了一個第三方的庫datajs,datajs最終會調用瀏覽器的底層http對象XMLHttpRequest:
要獲取更多Jerry的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: