基於ngMockE2E實現後臺資料模擬
引言
今天老大給了新任務,在開始給我說的時候讓我改造一個指引,上面的流程是比較簡單的,所以在開始的時候
沒有當回事,因為對這些東西比較熟悉了,但是在說完需求以後告訴我這個專案不建立後臺,所有的流程操作都在前
臺完成,這一下子就整懵逼了,沒有後臺數據怎麼辦,那些流程的流轉咋弄,結果老大說資料只需要模擬一份就可以
了,不需要入庫,但是上面的什麼流程啟動,傳送,儲存功能都需要實現。
在網上找了一些基於angular模擬後臺資料的方法,最終確定用ngMockE2E來實現,關於ngMockE2E的說明是這樣
的:
The ngMockE2E is an angular module which contains mocks suitable for end-to-end testing. Currently there is only one mock present in this module - the e2e $httpBackend mock.
其實ngMockE2E的工作原理這樣的:如果我們在module中引入了ngMockE2E這個模組,頁面中的所有的請求則不會
真正的請求到後臺,而是被其中的$httpBackend攔截,$httpBackend會提供相應的get、post、put、delte請求,一
旦請求地址和提供的地址想匹配則執行相應的方法。
簡單總結一下這麼做的好處:
1、如果你並不是介面api的開發者,使用mock資料你就不用等待介面api設計完成就可以開始本地開發
2、如果你自己開發介面的api,使用mock資料不僅可以讓你更專注於前端開發,還不比糾結於後端具體的細節實
3、你可以快速的開發內容而不用管後臺邏輯
4、建立mock服務還可以幫助你設計介面api的結構
5、mock資料服務還可以給其他angular元件在對應服務上做單元測試用
下面開始我們的Demo:
我們需要在html(index.html)頁面引入2個檔案 angular.js angular-mocks.js
<span style="font-size:18px;"><span style="font-size:18px;"><!DOCTYPE html> <html ng-app="app"> <head> <meta charset="utf-8" /> <title>AngularJS Plunker</title> <script src="angular.js"></script> <!--<script src="angular-resource.js"></script>--> <script src="angular-mocks.js"></script> <script>document.write('<base href="' + document.location + '" />');</script> <!--<link rel="stylesheet" href="style.css" />--> <script src="app.js"></script> </head> <body ng-controller="MainCtrl"> <p>All students:</p> <ul> <li ng-repeat="student in students">{{ student.name }}</li> </ul> <p>Student1: {{ ada.name }}</p> </body> </html></span></span>
所需要的檔案我已經上傳到csdn,在文章末尾有下載地址;
下面來看我們的app.js檔案的內容,首先看看我們的module以及依賴的模組
<span style="font-size:18px;"><span style="font-size:18px;">var app = angular.module('app', [
'ngMockE2E'
]);</span></span>
下面來完成我們的$httpBackend的定義,它的定義式需要通過一個run模組來完成的,在我們的demo中我們把它添
加到一個run模組中,然後定義一組students
<span style="font-size:18px;"><span style="font-size:18px;">app.run(['$httpBackend', function($httpBackend) {
students= [
{
id: 1,
name: 'Ada Lovelace',
phone: '8445551815'
},
{
id: 2,
name: 'Grace Hopper',
phone: '8445551906'
},
{
id: 3,
name: 'Charles Babbage',
phone: '8445556433'
}
];
// $httpBackend interactions are defined here...
}]);</span></span>
這個students陣列是mock backbend所有的操作都可以操作的,就像我們後臺的資料庫一樣,這是我我們建立前臺模擬資料庫的一種方式,另外幾種建立方式讀者自行學習。
下面我們先簡單的來模擬一個查詢學生的介面,用get方式請求後返回整個學生集合。
<span style="font-size:18px;"><span style="font-size:18px;">// Query; returns all students.
$httpBackend.whenGET('/students').respond(students<span style="font-family: SimSun;">);</span></span></span>
我們你需要發出一個get請求,請求地址為“/studnets”,則可以接收到所有的學生。
<span style="font-size:18px;"><span style="font-size:18px;"> $http.get("/students").success(function (data) {
$scope.students= data;
})
</span></span>
這樣我們就可以在頁面中迴圈輸出所有的學生的姓名。
下面我們來實現儲存的方法,也就是想students陣列中增加一條新紀錄,利用post請求攜帶student資料。
<span style="font-size:18px;"><span style="font-size:18px;">// Save; create a new contact.
$httpBackend.whenPOST('/students').respond(function(method, url, data) {
var newStudent = angular.fromJson(data);
students.push(newStudent);
return [200, newStudent, {}];
});</span></span>
因為angular元件會把資料當作json來處理且不會複查,所以一定要注意將序列化的學生資料轉成json。建立一
條新的紀錄就像在students陣列push一條資料一樣簡單。
如果我們想要在物件中獲取一條學生記錄就需要做兩件事情:從URL中獲取ID,根據id在陣列中取值。
$httpBackend.whenGET(/\/students\/(\d+)/, undefined, ['id']).respond(function(method, url, data, headers, params) {
var student= findStudentById(params.id);
if (student== null) {
return [404, undefined, {}];
}
return [200, student, {}];
});
我們用一個正則匹配url,獲取到id的集合。angular把匹配的到的結果儲存到params的id屬性上,也就是
whenGET方法的第三個入參。再抓去這個值傳到findStudentById方法中,將查詢的結果返回給我們。最後,我們返回
查詢結果,如果為空就返回404。
下面我們看一下findStudentById的方法的程式碼:
function findStudentById(id) {
var studentId = Number(id);
var matches = students.filter(function(student) {
return student.id === studentId;
});
var student = matches.shift();
return student;
}
下面來介紹更新的方法,和get方法是差不多的:
$httpBackend.whenPUT(/\/students\/(\d+)/, undefined, undefined, ['id']).respond(function(method, url, data, headers, params) {
var student = findstudentById(params.id),
parsedData = angular.fromJson(data);
if (student == null) {
return [404, undefined, {}];
}
angular.extend(student, parsedData);
return [200, student, {}];
});
同樣我們根據在URL截獲的id引數在陣列中查詢到對應的資料記錄,然後利用angular.extend方法將資料記
錄更新。
刪除方法同樣和上面的get或者put方法類似,先根據ID查詢到相應的記錄,然後刪除。
$httpBackend.whenDELETE(/\/students\/(\d+)/, undefined, ['id']).respond(function(method, url, data, headers, params) {
var student = findstudentById(params.id);
if (student == null) {
return [404, undefined, {}];
}
// Replace students array with filtered results, removing deleted student.
students.splice(students.indexOf(student), 1);
return [200, undefined, {}];
});
通過上面的GET、PUT、DELETE、POST等操作我們已經完成了對後臺的服務的模擬和資料的定義,到這我們的後臺模
擬就已經完成了,下面就是定義我們應用控制器,在這控制器我們將對服務進行呼叫來完成對後臺操作的模擬。
app.controller('MainCtrl', function($scope,$http) {
var tempData= {
name: '曉兒',
phone: '1221212212',
sex:'男'
};
$http.post("/students",tempData).success(function (data) {
console.log(data);
})
$http.put("/students/1",tempData).success(function (data) {
console.log(data);
})
$http.delete("/students/2").success(function (data) {
console.log(data);
})
$http.get("/students").success(function (data) {
$scope.students = data;
})
});
在這這個demo中我只是給大家簡單的列印了一下,沒有進行詳細的顯示,但是原理都是比較容易懂得,demo到這
給大家介紹的也差不多了,希望對大家有幫助。
再這在給大家介紹一個在上面demo中沒有寫的一個用法,就是API文件中提到的passThrough關鍵字,看一下這個
東西的基本用法:
$httpBackend.whenGET(/\/views\//, undefined, undefined).passThrough();
很多時候我們會遇到請求頁面地址的問題,但是我們並不希望在這個請求被攔截,讓頁面的渲染被阻止,也不需
要返回資料,這就需要我們的passThrough,像上面那樣符合請求地址的,則不進行阻攔。
PS:demo下載地址:點我下載