寫個JavaScript非同步呼叫架構(Part 1

來源:互聯網
上載者:User

問題

在Ajax應用中,調用XMLHttpRequest是很常見的情況。特別是以用戶端為中心的Ajax應用,各種需要從伺服器端擷取資料的操作都通過XHR非同步呼叫完成。然而在單線程的JavaScript編程中,XHR非同步呼叫的代碼風格實在是與一般的JavaScript代碼格格不入。

額外參數

考慮一個除法函數,如果它是純用戶端的同步函數,那麼簽名會是這樣的:

function divide(operand1, operand2)

然而假設我們對用戶端除法的精度不滿意,於是把除法轉移到伺服器端來執行,那麼它是個需要調用XHR的非同步函數,簽名也就可能會是以下幾種之一:

function divide(operand1, operand2, callback)
function divide(operand1, operand2, successCallback, failureCallback)
function divide(operand1, operand2, options)

我們必須在簽名中引入新的參數來傳遞迴調函數,不能選擇讓函數變成阻塞式的同步調用。

可傳遞性

不僅僅直接操作XHR的函數需要引入新的參數,這種複雜性還會順著調用棧向外傳遞。例如說,我們對加減乘除四則運算作了封裝,只向外暴露一個運算介面:

function calculate(operand1, operand2, operator)

這個calculate函數根據operator參數來調用內部的plus, subtract, multiply, divide函數。然而,因為divide函數變成了非同步函數,所以整個calculate函數不得不也轉變為非同步函數:

function calculate(operand1, operand2, operator, callback)

同時,在調用棧之上凡是需要調用到calculate的函數,都必須變成非同步,除非它並不需要向上一級調用函數返回結果。

同步並存

儘管calculate函數變成了一個非同步函數,它所調用的plus, subtract, multiply函數還是同步函數,只有調用divide時是非同步,這時候calculate就是一個非同步同步並存函數。

這會帶來什麼問題?calculate的調用者看到函數簽名自然會認為calculate是個非同步函數,因為它需要傳遞迴調函數,然而calculate的執行方式卻是不確定的。考慮如下調用:

calculate(operand1, operand2, operator, callback);
next();

這裡涉及到callback和next兩個函數,它們哪個先執行哪個後執行是不確定的,或者說是依賴於calculate具體實現的。

如果calculate的實現是,當不需要進行非同步作業時,直接調用callback。那麼,在執行加減乘法時callback會在next之前被調用;在執行除法時next會在callback之前調用。

如果我們不喜歡這種不確定性,我們可以改變一下calculate的實現,把同步調用也都改為setTimeout形式的,這樣在任何情況下next都一定會在callback之前被調用。

然而後面一種做法依賴於成本較高的實現方式,開發人員一個不小心(或者擺明偷懶)就會漏掉setTimeout,導致函數調用順序變得不確定,所以我們會希望這是架構協助實現的功能,在使用架構時無法把這繞過。

情境

在這裡,我舉一個關於上述問題的具體應用情境。(為簡化問題,描述已略作修改,與實際應用並不一致。)

在百度Hi網頁版裡面,我們會在用戶端儲存一個使用者物件列表,在開啟和這個使用者的聊天視窗時,我們需要從中讀取這個使用者的資訊。這個操作就涉及很多可能同步又可能非同步分支:

使用者物件未緩衝

非同步讀取使用者資訊

使用者物件已緩衝

使用者是好友(資訊更新會由伺服器端推送)

同步讀取使用者資訊

使用者不是好友(資訊更新需要由用戶端拉取)

可以接受緩衝資訊

同步讀取使用者資訊

必須擷取最新資訊

非同步讀取使用者資訊

可以看到,分支的結果最終既有同步的,也有非同步。並且這些分支還不是在一個函數裡完成,而是在幾個函數裡實現。也就是說,按照傳統的模式,這些函數一部分是同步的,一部分是非同步,由於非同步傳遞性,最終調用棧頂層的函數都是非同步。

為瞭解決這個問題,我們需要寫一個非同步呼叫架構,用一種統一的方式來進行調用,把同步和非同步呼叫都合并為一種返回方式。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.