前端不會這個就別想着還房貸了?論怎麼讓異步請求按請求順序返回

昨天晚上小夥伴發了我一個文章,標題很嚇人,叫《若是你想靠前端技術還房貸,你不能連這個都不會》,恰好戳中了我這個潛在富一代買不起房的痛點。嚇得我趕忙點進來看了一下,吭哧吭哧大概花了三個小時才搞出來,作完又開始發愁了,房貸可能交得起了,這首付是國家發仍是本身領呢。
好了不扯了回到正題html

問題

知乎地址 zhuanlan.zhihu.com/p/25259283
某個應用模塊由文本框 input,以及按鈕 A,按鈕 B 組成。點擊按鈕 A,會向地址 urlA 發出一個 ajax 請求,並將返回的字符串填充到 input 中(覆蓋 input 中原有的數據),點擊按鈕 B,會向地址 urlB 發出一個 ajax 請求,並將返回的字符串填充到 input 中(覆蓋 input 中原有的數據)。
當用戶依次點擊按鈕 A、B 的時候,預期的效果是 input 依次被 urlA、urlB 返回的數據填充,可是因爲到 urlA 的請求返回比較慢,致使 urlB 返回的數據被 urlA 返回的數據覆蓋了,與用戶預期的順序不一致。
請問如何設計代碼,解決這個問題?前端

建議能夠本身先嚐試一下看能不能寫出來
想看答案的能夠直接戳這裏ajax

問題分析

首先這道題確定是一個將異步隊列按同步的順序返回的問題。先返回的若是不是隊列的第一個任務,那麼結果將會被保留下來,一直等到隊列第一個任務返回時出棧,輪到本身到第一個隊列時才執行。promise

開始

首先咱們先寫html頁面

image

html很簡單,第一個按鈕點擊後等3s返回結果。第二個按鈕點擊1s後返回結果。爲了讓效果更明顯,咱們將返回的結果依次輸出在 container這個 class

而後咱們寫js代碼

咱們首先模擬兩個請求
異步

image
正常狀況下咱們的請求通常都是這樣的,返回一個promise。接下來看一下咱們對兩個按鈕進行方法綁定
image
這樣就完成了按鈕綁定,將返回的結果輸出到頁面中這個方法,可是因爲異步返回時間的不一樣,他們的順序並非按照點擊的順序來的,這裏就到了問題的難點了。如何讓異步的請求按照同步的結果返回?問題大概能夠概括爲幾個步驟

  1. 首先要有一個執行隊列,隊列中的內容即爲保存的請求
  2. 當保存的請求執行完畢時,給它設置一個執行完畢的狀態。同時觸發一個執行完畢的方法
  3. 在執行完畢的方法中,檢查隊列第一個索引中的內容是否執行完畢,若是執行完畢則執行後續代碼並移出隊列。判斷第二個是否也執行完畢,以此類推。
    代碼以下
    image
    這裏能夠看到,咱們用了一個createSyncTask方法,用高階函數的方法,將異步的隊列傳入,並返回一個組裝後的高階函數。當調用這個高階函數時,就向taskQueuepush進一個任務。同時讓它的Promise一直處於pending狀態,當執行完畢後,才改成resolve。同時觸發隊列中已經有任務完成的方法triggerTaskFinish
    triggerTaskFinish方法就很簡單了。判斷當前隊列第一個是否已經resolve,若是resolve。那麼就將它的Promise方法狀態設置爲resolve,同時將返回值傳入。
    那麼接下來,咱們只須要將原來的異步請求包裝一下便可實現需求
    image

    好了,那麼咱們就能夠實現任務是根據咱們點擊順序來實現的效果了。並且這種寫法,若是不須要同步了或者增長新的按鈕,後面改起來也比較方便。

完整js代碼以下
函數

image

總結

這道題感受最難的地方就是怎麼讓異步的請求能按請求的前後順序返回,當時爲了考慮代碼的維護性和複用性,最後用了一個單例對象(不知道算不算單例)和高階函數將常見的異步請求封裝成帶同步隊列的異步請求。固然結果還有不足之處,好比咱們沒有作異常處理,若是有一個請求跪了怎麼辦,這些就交給大家解決啦。url

若是有什麼不足的地方歡迎評論指正。畢竟我也只是個小前端設計

相關文章
相關標籤/搜索