標籤:
AngularJS中的RESTful資源
palwo
發表於 2014-12-16 17:31:50
$http服務提供了一個非常低級的實現,可以用來發送XHR請求,同時它還為你提供了很大的可控性和靈活性。但是,在大多數情況下,我們需要處理對象,以及封裝了特定屬性和方法的物件模型,例如一個person對象(帶有詳細資料),或者一個信用卡對象。
在這些情況下,如果我們能夠建立一個JS對象,而且它可以理解並代表這種物件模型,是不是會很棒?如果我們僅僅編輯這個對象的屬性,例如儲存或者更新,那麼這些狀態會被持久化到服務端嗎?
$resource就是為這一功能而設計的。AngularJS中的resource(資源)允許我們用描述性的方式來定義物件模型,它可以描述以下內容:
1.資源在服務端的URL。
2.常用的請求參數類型。
3.一些附加的方法(你可以自動獲得get、save、query、remove和delete方法),這些方法為物件模型封裝了特定的功能和商務邏輯(例如信用卡對象的charge()方法)。
4.期望獲得的響應類型(一個數組或者一個對象)。
5.協議頭。
使用Angular所提供的$resource對象,你可以根據各種需求查詢服務器;除此之外,你還可以把服務端返回的對象當成已經持久好的資料模型,你可以修改它們,並且可以把它們持久化。
ngResource是一個獨立的、可選的模組。為了使用它,需要:
a.在載入的指令檔中包含angular-resource.js
b.在模組依賴聲明中包含ngResource(例如,angular.module(‘myModule‘, [‘ngResource‘]))。
c.在需要的地方使用注入的$resource服務。
在學習如何使用ngResource方法建立資源之前,我們先來看看使用基本的$http服務建立類似的東西需要做些什麼事情。對於我們的信用卡資源來說,除了要能夠對它進行"change"(收費)操作之外,我們還要能夠get(擷取)、query(查詢)以及save(儲存)信用卡。
以下是一種可能的實現:
myAppModule.factory(‘CreditCard‘, [‘http‘, function($http) { var baseUrl = ‘/user/123/card‘; return { get: function(cardId) { return $http.get(baseUrl + ‘/‘ + cardId);}, save: function(card) { var url = card.id ? baseUrl + ‘/‘ + card.id : baseUrl; return $http.post(url, card);}, query: function() { return $http.get(baseUrl);}, charge: function(card) { return $http.post(baseUrl + ‘/‘ + card.id, card, {params: {charge: true}});}};}]);
除了這種方式之外,還可以簡單地建立一個Angular服務,這個服務將會通過以下方式來描述應用所提供的資源:
myAppModule.factory(‘CreditCard‘, [‘$resource‘, function($resource) { return $resource(‘/usr/:userId/card/:cardId‘, {userId: 123, cardId: ‘@id‘}, {charge: {method: ‘POST‘, params: {charge: true}, isArray: false});}]);
現在,只要向我們AngularJS注射器請求一個CreditCard執行個體,我們就可以擷取一個Angular資源,它預設為我們提供了一些基礎的方法。下表列出了這些方法的內容以及它們的行為,有了這些資訊你就知道應該如何佈建服務端了。 下面我們來看一個信用卡的執行個體,這會讓我們的思路更加清晰。
//假設CreditCard服務被注入到了這裡//我們可以從服務端擷取一個集合,請求的路徑為GET:/user/123/cardvar cards = CreditCard.query();//我們還可以在回呼函數中擷取並使用單張信用卡CreditCard.get({cardId: 456}, function(card) {//每個執行個體都是CreditCard類型 expect(card instanceof CreditCard).toEqual(true); card.name ="J.Smith";//非GET型的方法被映射到了執行個體上card.$save();//我們自訂的方法也被映射上去了card.$charge({amount:9.99});//發起一個POST請求:/user/123/card/456?amount=9.99&charge=true //發送請求時傳遞的資料為:{id:456, number: ‘1234‘, name: ‘J.Smith‘}});
這個例子涉及了比較多的內容,對於其中比較重要的內容依次介紹如下:
一.聲明
無論是自已定義$resource,還是使用正確的參數來調用注入的$resource函數,操作都非常簡單。
$resource函數有一個必要參數,即可用資源的URL地址,還有兩個可選的參數,即預設參數以及你想配置在資源上的額外動作。
請注意URL是參數化的(用:來標識參數。:userId表示userId將會被替換成對應的文本,:cardId表示將會被cardId實參的值替換掉)。如果沒有傳遞參數,對應的標識符會被替換成Null 字元串。
第二個參數負責處理每一個請求中都會被發送的預設值。在當前這個例子中,我們會把常量123傳遞給userId。參數cardId更加有趣,“cardId是"@id."”表示的是,如果我們正在使用一個從服務端返回的對象,那麼當調用這個對象上的任意方法時(例如調用對象的$save方法),對象上的id屬性值就會被賦給cardId參數。
第三個參數是另一個函數,我們希望在自訂的資源上暴露這個函數。
二.自訂方法
調用$resource時,傳遞的第三個參數是一個可選的。我們希望在自已的資源上暴露的方法。
在前面的例子中,我們指定了一個charge方法,可以通過傳遞一個對象來配置這個方法,對象中的key就是需要暴露的方法名稱。配置項中需要指定的內容有:請求的類型(GET、POST等)、需要作為請求的一部分來傳遞的參數(在這個例子中就是charge=true),以及返回的結果是否是一個數組(在這個例子中不是)。一旦做完這些事情之後,你就可以自由地調用CreditCard.charge()了
說明:這是一種非常靈活的編碼風格,根據上面的代碼,對於設定物件{charge: {method: ‘POST‘, params: {charge: true}, isArray: false},Angular會將其解析成一個方法,然後把這個方法綁定到返回的Restful對象上,上面的設定物件解釋之後的方法為:
CreditCard.charge = function(charge, isArray) {//這裡是方法體}
三.別用回調!(除非你真的需要它們)
第三個需要注意的內容是調用資源時的傳回值類型。請再看一下CreditCard.query()調用,我們直接把信用卡對象賦值給了card變數,而並沒有在回呼函數裡面進和賦值。你可能會擔心在對伺服器進行非同步請求的情況下,這種代碼能運行嗎?
你這種擔心是合理的。但事實上,這段代碼完全正確,並且能夠運行。這裡發生的事情是,AngularJS賦給了card對象一個引用(一個對象或者數組,具體是什麼需要根據所期望的傳回值類型而定),在未來的某個時間上,當對伺服器的請求返回來之後,這個引用才會被真正賦值。在些期間,引用對象一直是空的。
對於AngularJS應用來說,最常見的處理流程是:到伺服器上擷取資料,然後把資料賦值給變數,再把資料顯示到模板中。這種捷徑是非常好用的。在控制器代碼中,你唯一要做的事情就是發起對服務端的調用,把傳回值賦給正確的範圍變數,然後讓模板自動負責渲染它。由於card變數是使用{{}}這種資料繫結技術綁定到視圖上的,所以一開始給它一個空值並沒有問題,等非同步響應返回之後再把結果賦給它。這時候Angular的資料繫結機制會立即探索資料發生了變化,然後會自動通知視圖進行重新整理。從這裡可以看到,使用Angular架構時,對非同步呼叫的很多處理方式已經發生了細微的變化。
如果你有一些需要依賴於傳回值才能執行的商務邏輯,那麼這種方法就不會奏效。在這種情況下,你就需要使用回呼函數,這個回呼函數會在調用CreditCard.get()的時候被使用。
四.簡化服務端操作
無論你使用傳回值的捷徑,還是使用回呼函數,都有一些關於返回對象的注意事項。傳回值不是普通的JS對象,而是一個"resource"型的對象。這就意味著,除了服務端返回的資料之外,它上面還帶有一些附加的行為(在這個例子中就是$save()和$charge())。這樣可以讓你更容易進行服務端調用,例如擷取資料、修改資料,以及把修改的內容持久化到服務端(也就是在很多應用中都很常見的CRUD操作)。
五.何時可以使用Angular資源
只有服務端按照RESTful的方式工作的時候,你才可以使用Angular資源。對於信用卡情境,它需要:
1.一個到/user/123/card的GET請求,它會返回使用者123的信用卡列表。
2.一個到/user/123/card/15的GET請求,它會返回使用者123的ID為15的信用卡。
3.一個到/user/123/card的POST請求,在POST的資料中帶有信用卡資訊,它將會為使用者123的ID建立一張新的信用卡。
4.一個到/user/123/card/15的POST請求,POST的資料中帶有信用卡資訊,它將會更新使用者123的ID為15的信用卡資訊。
5.一個到/user/123/card/15的DELETE請求,它將會刪除使用者123的ID為15的信用卡資訊。
angularjs $resource restful api