使用angularjs1.x構建前臺開發框架(四)——模擬後臺響應(打樁模組)
為什麼要模擬後臺響應(打樁模組):在web應用開發中,往往會有前臺需要呼叫後臺介面獲取資料進行頁面除錯但後臺介面未開發完成的情況,因為架構師在分解需求的時候前後臺需求是一起給出的,開發也是並行的,那麼在後臺沒有ready的時候,前臺只能乾等嗎?當然不是。架構師在完成需求分解的時候通常需要交付一個非常重要的文件——介面文件,而本章介紹的模擬後臺響應(打樁模組)正是基於後臺未開發完成但已經有完備介面文件的情況下幫助前臺開發人員完成獨立除錯的一個功能模組(當然,這個功能模組也屬於開發框架的一部分)。
在介紹模擬後臺響應(打樁模組)之前,先來看一下如何在開發框架中發起http請求(通常請求在業務模組中會比較多,所以這個請求筆者放在c2這個自路由對應的業務模組中)。
首先在c2.html中構造發起請求的按鈕(第3行):
<div>
<input type="button" value="test Controller" ng-click="test()">
<button ng-click="getData()">request</button>
</div>
點選按鈕時會呼叫控制器中定義的getData()方法,接下來我們看一下在c2.js中對getData()方法的定義(第10行~第22行):
/** * Created by 李慶 on 2016/10/6. */ define(["jquery"],function($){ var c2Controller = function($scope){ $scope.test = function(){ console.log("enter controller"); }; $scope.getData = function(){ $.ajax({ "type":"GET", "contentType":"application/json;charset=UTF-8", "url":"mock/test.json", "success":function(data){ console.log(JSON.stringify(data)); }, "error":function(data){ console.log("error"); } }); } }; return c2Controller; });
getData()會發起一個http請求,請求本地的一個資源(mock下的test.json),當請求成功時,會在控制檯列印響應的資訊(即返回的json字串)。
然後我們來看一下這個test.json包含的資訊:
{
"name":"liqing"
}
再看一下資源在整個工程中的位置以及現在的工程目錄結構:
最後我們來看一下執行效果:
可以看到當我們點選request按鈕時,控制檯列印了我們請求的資源,也就是對應test.json的內容。至此,一個完整的http請求過程就完成了。
下面先簡單介紹一下打樁模組的功能:打樁通常用於寫測試用例的時候,依賴的介面或資源無法直接直接呼叫獲取(比如在規模較大的應用中,為了驗證一個函式,就得把整個應用都跑起來,不僅資源浪費嚴重,效率也非常低),在不影響測試的基礎上,測試人員會模擬依賴的外部介面或資源,當呼叫依賴的介面或資源時,不會真的呼叫依賴的介面或資源,而是獲取之前模擬的資料,這個模擬資料的行為稱為打樁,而在筆者的開發框架中,打樁模組的功能也是類似的,也是由於後臺介面未開發完成導致無法聯調,因此發起http請求時不直接向後臺介面請求,而是由打樁模組代答,當然,我們必須在打樁模組中事前構造號好代答資料。
在框架中的打樁過程:所有需要打樁的請求url都需要由過濾模組過濾,過濾模組決定請求是否需要打樁,如需要,則返回樁資料url,如不需要,則反正真實的後臺介面url。
下面來看一下程式碼,首先是新增的http請求過濾模組httpService.js,這個模組定義了所有樁資料的路徑以及決定請求是向後臺請求還是樁資料請求:
/**
* Created by 李慶 on 2016/10/23.
*/
define([],function(){
var mock = true;//打樁標識,false表示不打樁,true表示打樁
var httpService = new Object();
/***
*
* httpService.data包含所有需要打樁的請求
*/
httpService.data = [
{
"type":"GET",//請求型別
"url":"/nova/test.json",//請求url
"mockUrl":"mock/test.json"//打樁url
}
];
httpService.getUrl = function(type,url){
if(mock){
for(var i=0;i<httpService.data.length;i++){
if(httpService.data[i].url == url && httpService.data[i].type == type){
return httpService.data[i].mockUrl;
}
}
}else{
return url;
}
};
return httpService;
});
c2.js的變更,增加了對過濾模組httpService的依賴,且請求url由過濾模組進行過濾(第4行和第15行):
/**
* Created by 李慶 on 2016/10/6.
*/
define(["jquery","../../../framework/service/httpService"],function($,httpService){
var c2Controller = function($scope){
$scope.test = function(){
console.log("enter controller");
};
$scope.getData = function(){
$.ajax({
"type":"GET",
"contentType":"application/json;charset=UTF-8",
//修改前為"url":"mock/test.json",
"url":httpService.getUrl("GET","/nova/test.json"),
"success":function(data){
console.log(JSON.stringify(data));
},
"error":function(data){
console.log("error");
}
});
}
};
return c2Controller;
});
最終呈現的結果和前面發起http請求的結果是一樣的,在這裡就不重複貼了。
為什麼這裡的樁資料路徑和前面發起http請求例子裡面的資源路徑是一樣的?其實前面發起http請求例子裡面的資源也可以視為一個樁資料,整個請求過程同樣可以視為一個原始的打樁,我們可以通過修改請求url來實現請求資源路徑的切換,但是這樣做代價是巨大的,當我們頁面中有多個請求都需要打樁時,就必須手動一個一個去修改,費時費力不說,還容易出錯,而框架的打樁模組只需要設定一下mock的值就可以完成打樁和不打樁的切換,非常方便,這也正是打樁模組存在的意義。而反過來說,如果請求的資源真的是服務端的一個靜態資料,那整個過程和打樁其實沒有分別:真正的請求和樁資料有的時候界限並不是那麼清晰。
下面來說一下怎麼使用打樁模組:
1.打樁與不打樁的切換:
httpService.js中的mock變數決定整個應用的請求(有需要打樁的請求)是否需要打樁,true表示需要打樁,false表示不需要打樁;
當我們關閉打樁開關而後臺服務又沒有準備時,嘗試發起請求:
可以看到請求的路徑是真實的url,而由於後臺未準備,響應結果是404資源不存在。
2.怎麼為一個請求構造打樁模組:
首先,宣告對httpService的依賴,並讓httpService過濾希望打樁請求的url(傳遞的引數是請求型別和真實的請求url):
然後在httpService中宣告請求的樁資料路徑:
最後為請求構造樁資料,所有樁資料建議放在同一個目錄下(即mock目錄):
3.使用打樁模組的注意事項:
絕對絕對不能把打樁開關設定為true以後提交到程式碼庫中,因為最終做出來的包必然是不包含樁資料的,那麼這個時候所有的請求都會無法請求到資源。
為請求構造了打樁模組以後一定要及時合入,否則很容易導致重複打樁或者程式碼衝突。
最後說一下打樁模組的擴充套件:
如果我們希望post請求的樁資料可以根據post資料的不同而有所變化,該怎麼處理?
httpService並沒有處理post過來的資料,即上面給出的程式碼如果應用在post請求上是不care post過來的資料的,如果需要處理,則要擴充套件httpService的getUrl方法,接收post資料,並在內部處理(當post資料不同時,根據新增的處理邏輯,指向不同的樁資料)。
請求url包含引數時,該怎麼處理?
httpService的getUrl方法中的url比較不能直接使用==,在httpService中定義url時應定義為一個正則表示式,比較url是否相同的時候使用正則匹配。