一個基於jQuery ajax和.net httphandler 的超輕非同步框架

iDotNetSpace發表於2010-05-20
  • 背景

  •         我部正在開發的一個新專案,選擇了jQuery作為基礎的Javascript函式庫。同時確定了jQuery提供的ajax系列方法作為非同步推拉資料的基礎介面。

    使用過ajax方法的同事應該是知道的,ajax方法需要提供一組選型,比如content-typemime-typedataasync等等,這些選項的組合搭配可以構成不同的請求方式,必須理解HTTP的部分協議才能夠正確的完成配置。當然,也可以從google上去找配置好的程式碼片段copy過來用, 關於這種方式的缺陷就不多說了。

     

  • 我的失誤

  • 1.      沒有在程式碼編寫之前,規定好如何利用jQueryajax方法。導致開發人員直接把ajax方法的呼叫寫在頁面的指令碼塊內,導致頁面內出現瞭如下所示的程式碼:

     $.ajax({ type: "post", contentType: "application/json",datatype: "json", async: false, url: "DemoHandler.asmx/GetData",data: "{index:1}", complete: function(e, s) { alert("ok")});

     

  • 分析現象

  •        上面的程式碼的意圖是通過httppost方法,呼叫服務端web servicesGetData方法,傳入的引數名稱為index,值為1 。這是以硬編碼方式與服務端達成的強耦合關係的編碼方式,隱含了如下的問題:

    1.      DemoHandler.asmx檔案的路經改變了,就會影響頁面內所有這樣的程式碼;

    2.      服務端GetData的方法簽名如果變化了,就會影響頁面內所有這樣的程式碼;

    3.      如果以後出現了更好的ajax框架,替換的工作量也是如同推倒重來的;

    4.      GetData這樣的方法如果被其他地方呼叫,採用的方法是copy一段這樣的程式碼;

    5.      當我們提倡前後臺分開的開發的情況下,理論上前臺開發人員精通的技術應該是div+cssjs這些,後臺開發才關注web services這樣的技術。只有這樣才能把各自的領域做精、最好。上面所示程式碼的第一個模板是我提供的,因為我個人扮演了聯通前臺和後臺技術的橋樑角色,但反思起來他是個人行為,卻不是團隊力量的體現。

    6.      開發人員可以自問一下,contentType: "application/json" 這個選項起到什麼作用?為什麼DemoHandler.asmx/GetData這樣的寫法可以成功調入到web services方法內部?為什麼data要寫成 "{index:1}" 這樣的樣式?我嘗試問了專案組的人,答案都是不知道。很明顯,真正和開發有關的只是業務,而不是這些底層協議方面的知識,它是可以對大家遮蔽的。

     

  • 解決辦法

  •        當把存在的問題分析清楚了,答案也就有了。我們為每一個web serivices寫一個專門的js檔案,它內部封裝了一組與web method一致簽名的函式。這樣頁面只通過js方法傳引數呼叫即可,而不再關注那些ajax呼叫選項的細節。達到了相關概念的邏輯統一封裝和管理、一點維護多點使用、不同職責的開發人員關注不同功能這些要求。

           在這件事情的執行上,又出現了一個小插曲。負責寫js檔案的同學參考了其它網上牛人的js書寫風格,也玩起了風靡一時的js花招動態物件、閉包。當然很快就被否定了,其它原因不多講,只有一點原因需要特別說明:任何程式設計技巧和技術的使用都要考慮它是否適合團隊中的一般水平,如果不適合就要考慮其它辦法。閉包顯然只是一個技巧而已,不是解決問題的王道。它的引入至少給一般人閱讀程式碼增加了難度,所以要被PASS掉。

    最終還是選擇採用大白話式的prototype來宣告服務物件的方法。一開始,我寫了一個頭部的初始化函式,該函式封裝好了所有的選項配置資訊,以及把服務物件擴充套件到jQuery體系中去,使開發人員可以按照一致的規格呼叫服務端函式。後期,其他開發人員只要在檔案的尾部按需追加一個個與服務端方法對應的函式即可。

     

  • 優化與改進

  • 為了利用.net script. servicesweb services的擴充套件,專案組一開始規定後臺直接提供web services對客戶端進行暴露。這對客戶端提交資料沒有問題,但對我們使用的某些控制元件就不太適合了。因為控制元件要求返回值是一個純粹的json資料,而script. services框架會在輸出的json資料外層再包上一個名d的根,這就導致控制元件無法識別這個資料來源。於是專案組通過ashx檔案,實現Ihttphandler來手動處理請求。

    很快,服務端工程裡多出了10幾個ashx檔案,因為客戶端需要10幾種不同的資料請求。每個ashx內部的ProcessRequest方法處理四件大事:1)設定WEB反饋的HTTP頭資訊;2)處理業務邏輯;3)序列化業務資料為JSON4)把JSON資料寫到輸出流中。

    這個現象說明了兩個問題:1ashx檔案的數量會隨著應用需求的增多而不斷的增多,今後非常難以維護;2)四件事情只有一件是必須每次都做的,即處理業務邏輯,其它事件都是有規律並重復的。

    基於對上述問題,專案組做出了改進,實現一個統一的WEB請求的排程和處理機制,使得同一類的請求可以放在一個ashx檔案內完成,並且每個請求直接對映到一個函式來完成,輸出、輸出、快取都由這個機制來處理;另外,普通開發人員只需要完成業務邏輯程式碼即可,其它一概不要關心。

           時間又過了2天,新的問題再此困擾了我。如果服務端增加一個新的方法,客戶端的js也要與之匹配的增加一個函式作為呼叫代理。這樣同一語意的函式,就產生了前後臺兩點維護,這是不合理的。它也是一個機械性的工作,每次都要開發手動來做,這也是不人性的。於是,新的解決方法是當客戶端直接請求ashx檔案的時候,服務端自動生成相應的客戶端代理指令碼。這樣帶來了客戶端程式碼更大的改進,我們只需要將 置入頁面,一切就OK了。因為自動獲得的js指令碼會自動初始化客戶端服務,後續就可以在頁面的任何地方通過例如這樣的方法呼叫服務了: $.net. xHandler.GetData()

    這樣改進之後,專案組的開發人員是充滿喜悅的,因為他們可以少做很多不必要的事情,可以把程式碼寫的更加整潔,可以讓BUG變的更少。從此,我們也把整合jQuery.ajax.net的技術方案固化了下來,以後團隊將依賴存在的技術穩定的工作,而不再依賴個人。順便說一句,在我們寫出這些程式碼的時候,已經考慮過例如ajaxpro.net.NET MVC這樣的框架,只是他並不適合我們而已。

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

    相關文章