標籤:
REST(表徵性狀態傳輸,Representational State Transfer)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟體架構風格。RESTful風格的設計不僅具有更好的可讀性(Human Readable),而且易於做緩衝以及伺服器擴充(scalability)。REST風格體現在URL設計上:
- 每個URL對應一個資源
- 對資源的不同操作對應於HTTP的不同方法
- 資源表現形式(representation)通過
Accept
和Content-Type
指定
AngularJS提供了$resource
Service來更方便地與RESTful伺服器API進行互動,可以方便地定義一個REST資源,而不必手動所有的聲明CRUD方法。
參考文檔: https://docs.angularjs.org/api/ngResource/service/$resource
Resource Factory
$resource
Service定義在ngResource
Module中,需要在你的HTML中引入這個Module對應的JS,同時在你的APP中添加這樣一個依賴:
var app = angular.module(‘helloApp, [‘ngResource‘]);
然後為資源建立一個Factory:
app.factory(‘Notes‘, [‘$resource‘, function($resource) { return $resource(‘/notes/:id‘);}]);
當然,你也可以不把$esource
的執行個體放到Factory裡,直接在控制器中存起來:var Notes = $resource(‘/notes/:id)
。
CRUD
在你的控制器中就可以對資源進行增刪改查了:
app.controller(‘NotesCtrl‘, [‘$scope‘, ‘Notes‘, function($scope, Notes) { var notes = Notes.query(function(){ // GET: /notes // Response: [{id: 1, content: ‘hello‘}, {id: 2, content: ‘world‘}]; var first = notes[0]; first.content = ‘halo‘; first.$save(); // POST: /notes/1 {id: 1, content: ‘halo‘} // Response: {id: 1, content: ‘halo‘} second.$delete(); // DELETE: /notes/2 }); var note = new Notes({content: ‘xxx‘}); note.$save(); // POST: /notes // Response: {id: 3, content: ‘xxx‘}}]);
PUT 操作
$resource
提供了五種預設操作:get
, query
, save
, remove
, delete
。你可以配置一個update
操作來完成HTTP PUT:
app.factory(‘Notes‘, [‘$resource‘, function($resource) { return $resource(‘/notes/:id‘, null, { update: { method:‘PUT‘ } }); }]);
現在,你可以在控制器中擷取一個note並更新它:
var note = Notes.get({ id: 3}), $id = note.id;note.content = ‘yyy‘;Notes.update({ id:$id }, note);// PUT /notes/3 {id: 3, content: ‘yyy‘}
現在你的Notes
有六種操作了。這些操作有兩種調用方式:
- 通過資源類調用,例如:
Notes.update({id: xxx})
;
- 通過資源執行個體調用,例如:
note.$update()
,此時操作名需加首碼$
。
具體的調用參數可參考文檔:
HTTP GET "class" actions: Resource.action([parameters], [success], [error])
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
non-GET instance actions: instance.$action([parameters], [success], [error])
其中,success參數為(value, responseHeaders)
,error參數為(httpResponse)
。
屬性/URL映射
上述例子中,我們看到note對象的id
屬性會映射到URL中的:id
(/notes/:id
)。如果你的業務更加複雜,可以手動設定這個映射關係。例如:
var Notes = $resouce(‘/users/:userId/notes/:noteId‘, { noteId: ‘@id‘, userId: ‘@owner‘}
將會讀取note
的owner
和id
屬性來產生URL,比如刪除note時:
// note === {id: 123, owner: ‘alice‘, content: ‘hello‘}note.$delete();// DELETE: /users/alice/notes/123
在構造$resource
時,多於的屬性對應會成為URL Query。例如:
var Notes = $resouce(‘/notes/:id‘, { id: ‘@id‘, user: ‘@owner‘});// note === {id: 123, owner: ‘alice‘, content: ‘hello‘}note.$delete();// DELETE: /notes/123?user=alice
REST操作的聲明和調用中,多於的屬性會成為URL Query。例如:
var Notes = $resouce(‘/notes/:id‘, {id: ‘@id‘}, { update: {method: ‘PUT‘, operator: ‘bob‘}});// note === {id: 123, content: ‘hello‘}note.$update({trusted: true});// PUT: /notes/123?operator=bob&trusted=true {id: 123, content: ‘hello‘}
響應轉換
有時基於既定的後台設計,無法提供完全RESTful的API,比如/notes
返回的是一個分頁器對象,而非數組。此時,我們仍然可以使用$resource
,但需要設定響應轉換回調。例如:
var Notes = $resouce(‘/notes/:id‘, null, { pager: { method: ‘GET‘, transformResponse: function(data, headers){ // Server respond: // data = {currentPage: 1, // totalPage: 20, // pageSize: 2, // content: [{id: 1, content: ‘hello‘}, {id: 2, content: ‘world‘}]} var pager = JSON.parse(data); return pager.content; } }});var notes = Notes.query(function(){ // GET: /notes // notes === [{id: 1, content: ‘hello‘}, {id: 2, content: ‘world‘}]});
類似響應重寫,你還可以佈建要求轉換transformRequest
。
雖然$resource
的設計可以支援絕大多數的URL和內容表示設計,但如果你發現$resource
的使用過程極其複雜,那可能是你的伺服器API並不滿足RESTful風格。
除非註明,本部落格文章均為原創,轉載請以連結形式標明本文地址: http://harttle.com/2015/06/05/angular-resource.html
AngularJS Resource:與 RESTful API 互動