在angular中有一個特別為RESTful架構而定製的服務,是在$http的基礎上進行了封裝.
但是為了學習,我們先看看用直接$http是如何構建RESTful架構的:
假設有一個銀行卡的列表.需要的功能有:
可以通過id來獲取使用者123的指定id的卡 'GET' 'card/user/123/id'
可以獲取使用者123的所有的銀行卡 'GET' 'card/user/123'
可以更新使用者123的指定id的卡 'POST' 'card/user/123/id'
可以為使用者123新增一張銀行卡 'POST' 'card/user/123'
可以刪除使用者123的指定id的卡 'DELETE' 'card/user/123/id'
html:
<!DOCTYPE html> <html ng-app = 'HttpREST'> <head> <title>18.5 $http(RESTful)</title> <meta charset="utf-8"> <script src="angular.js"></script> <script src="script.js"></script> <style type="text/css"> *{ font-family:'MICROSOFT YAHEI'; font-size:12px } </style> </head> <body> <div ng-controller = "Card"> <button ng-click="updataCard()">更新id為3的銀行卡</button> <br/> <button ng-click="addCard()">新增一張新的銀行卡</button> <br/> <button ng-click="delCard()">刪除id為3的銀行卡</button> <br/> <span>{{card_1}}</span> <br/> <span>{{card_2}}</span> <br/> <span>{{card_3}}</span> <br/> <span>{{card_4}}</span> <br/> <span>{{cards}}</span> </div> </body> </html>
js:
var HttpREST = angular.module('HttpREST',[]); HttpREST.factory('httpCard',function($http,$q){ var baseUrl = '/card/user/123'; return { //獲取使用者123的指定id的卡 getById:function(id){ var defer = $q.defer(); $http({ method:'get', url:baseUrl+'/'+id }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise }, //獲取使用者123的所有卡 query:function(){ var defer = $q.defer(); $http({ method:'get', url:baseUrl }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise }, //儲存一張卡,如果原來就有id,那就是更新這張卡,如果原來沒有這張卡,那就是新建這張卡, //新建路徑就是baseUrl,更新路徑就是baseUrl+id save:function(card){ var defer = $q.defer(); var url = card.id ? baseUrl+'/'+card.id : baseUrl; $http({ method:'post', url:url, data:card }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise }, //刪除使用者123的指定id的卡 del:function(id){ var defer = $q.defer(); $http({ method:'delete', url:baseUrl+'/'+id }).success(function(data){ defer.resolve(data) }).error(function(data){ defer.reject(data) }); return defer.promise } } }); HttpREST.controller('Card',function($scope,httpCard){ //通過id獲取銀行卡 $scope.card_1 = httpCard.getById(1); $scope.card_2 = httpCard.getById(2); $scope.card_3 = httpCard.getById(3); //獲取所有的銀行卡 $scope.cards = httpCard.query(); //更新id為3的銀行卡 $scope.updataCard = function(){httpCard.save({id:3,name:"工商銀行"}).then(function(data){$scope.card_3 = data['name']})}; //新增id為4的銀行卡 $scope.addCard = function(){httpCard.save({name:"浦發銀行"}).then(function(data){$scope.card_4 = data['name']});}; $scope.delCard = function(){httpCard.del(3).then(function(data){$scope.card_3 = data});} });
node:
var express = require('express'); var app = express(); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.static(__dirname)); var cards = [ { id:1, name:'建設銀行' }, { id:2, name:'中國銀行' }, { id:3, name:'上海銀行' } ]; app.get('/card/user/123/:id',function(req,res){ var data = cards[req.params.id-1]; res.send(data['name']) }); app.get('/card/user/123',function(req,res){ var data=[]; for(var i in cards){ data.push(cards[i]['name']) } res.send(data) }); app.post('/card/user/123/:id',function(req,res){ var index = req.params.id-1; cards[index] = req.body; res.send(cards[index]); }); app.post('/card/user/123',function(req,res){ var index = cards.length; cards[index] = req.body; cards[index].id = index; res.send(cards[index]); }); app.delete('/card/user/123/:id',function(req,res){ var index = req.params.id-1; cards[index] = null; console.log(cards); res.send(cards[index]) }); app.listen(3000);
1. 這裡檢視中的card_1,card_2,carde_3,card_4需要顯示的是銀行卡的name屬性,所以在後臺中直接返回卡的name值,而不是返回一整張卡再取name屬性
2. 建立一個名為httpCard的服務,這個服務返回的物件有四個方法:
①getById: 通過id獲取指定的卡的名字,顯示在檢視中就是card_1,carde_2,card_3
getById:function(id){ var defer = $q.defer(); $http({ method:'get', url:baseUrl+'/'+id }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise }
$scope.card_1 = httpCard.getById(1);
$scope.card_2 = httpCard.getById(2);
$scope.card_3 = httpCard.getById(3);
注意,必須使用$q,這樣可以確保在獲取到後臺的資料後渲染檢視.但是注意,$scope.card_1其實是一個promise物件,它不是真正返回到的data,真正的data是promise物件的$$v,這個在下一篇講ngResource時會詳細介紹,這裡只要瞭解到,通過promise,檢視可以獲取到返回的值.
②query: 獲取全部的卡的名字的陣列.顯示在檢視中就是cards
query:function(){ var defer = $q.defer(); $http({ method:'get', url:baseUrl }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise } $scope.cards = httpCard.query();
③save: 儲存指定id的卡(修改),或者儲存一張新建的卡(新建). 顯示在檢視中就是card_3 和 card_4
save:function(card){ var defer = $q.defer(); var url = card.id ? baseUrl+'/'+card.id : baseUrl; $http({ method:'post', url:url, data:card }).success(function(data){ defer.resolve(data); }).error(function(data){ defer.reject(data); }); return defer.promise } //更新id為3的銀行卡 $scope.updataCard = function(){httpCard.save({id:3,name:"工商銀行"}).then(function(data){$scope.card_3 = data['name']})}; //新增id為4的銀行卡 $scope.addCard = function(){httpCard.save({name:"浦發銀行"}).then(function(data){$scope.card_4 = data['name']});};
save方法都是POST型別的請求,傳入的引數就是請求體,根據請求體是否有id來判斷是更新卡還是新建卡.在後臺進行不同的處理.返回的值都是儲存的卡.
注意,save方法返回的也是一個promise,它的then方法裡的函式會在請求完成(也就是defer.resolve或者defer.reject,也就是得到了響應體)以後才被執行,引數就是請求返回的值,在這裡也就被儲存的卡(無論是更新還是新建),
然後$scope.card_3 = data['name'],這個時候,card_3不再是promise物件了,而真的是一個資料了.在ngResource中,處理方法會和此處有所不同.會在下一篇中詳解.
④del: 刪除指定id的卡.顯示在檢視中就是card_3
del:function(id){ var defer = $q.defer(); $http({ method:'delete', url:baseUrl+'/'+id }).success(function(data){ defer.resolve(data) }).error(function(data){ defer.reject(data) }); return defer.promise } //刪除id為3的銀行卡 $scope.delCard = function(){httpCard.del(3).then(function(data){$scope.card_3 = data});}
刪除和儲存性質是一樣的,都是返回一個promise物件,響應成功後得到響應體作為引數被傳入then的函式中,然後被執行.由於是刪除,所以返回null,card_3就變成了null,檢視中的card_3也就不見了
順便提一下,node裡需要使用express.methodOverride(),這樣就可以為app建立處理deletel方式的請求了.
app.use(express.methodOverride());
app.delete('/card/user/123/:id',function(req,res){
var index = req.params.id-1;
cards[index] = null;
console.log(cards);
res.send(cards[index])
});
執行node後,看到的頁面如下:
1.獲取到了card_1,card_2,card_3,cards
2.點選更新id為3的銀行卡,card_3變為'工商銀行'
3.點選新增一張新的銀行卡,card_4顯示為'浦發銀行'
4.點選刪除id為3的銀行卡,card_3就被清除了
完整程式碼地址: https://github.com/OOP-Code-Bunny/angular/tree/master/OREILLY/18.5%20%24http(RESTful)