web-dev-qa-db-ja.com

AngularJS $リソースのRESTfulな例

私はRESTfulなWebサービスを呼び出すために$ resourceを使いたいのですが(私はまだ取り組んでいます)、AngularJSスクリプトが最初に正しいかどうかを調べたいと思います。

ToDo DTOには次のものがあります。{id, order, content, done}

:cmdは、api/1/todo/resetを呼び出して、データベース内のToDoテーブルをクリアすることができます。

これが私の理解のコメント付きのコードです:

function TodoService($resource) {
    var src = $resource('api/1/todo/:id:cmd',
              {id: "@id", cmd: "@cmd"}, //parameters default
              {
                ListTodos: { method: "GET", params: {} },
                GetTodo: { method: "GET", params: { id: 0 } },                            
                CreateTodo: { method: "POST", params: { content: "", order: 0, done: false } },
                UpdateTodo: { method: "PATCH", params: { /*...*/ } },
                DeleteTodo: { method: "DELETE", params: { id: 0 } },
                ResetTodos: { method: "GET", params: { cmd: "reset" } },
              });

    //Usage:

    //GET without ID
    //it calls -> api/1/todo
    src.ListTodos();

    //GET with ID
    //it calls -> api/1/todo/4
    src.GetTodo({ id: 4 });

    //POST with content, order, done
    //it calls -> api/1/todo
    src.CreateTodo({ content: "learn Javascript", order: 1, done: false });

    //UPDATE content only
    //it calls -> api/1/todo/5
    src.UpdateTodo({ id: 5, content: "learn AngularJS" }); 

    //UPDATE done only
    //it calls -> api/1/todo/5
    src.UpdateTodo({ id: 5, done: true });

    //RESET with cmd
    //it calls -> api/1/todo/reset
    src.ResetTodos();
}

私が確信が持てない1つの特別なことはPATCHメソッドです、私はすべてを更新したくありません、私は1つのフィールドだけを更新することができますか?このコードを正しく構築できますか?

143
Tom

$ resourceは、エンドポイントからデータを取得し、それを操作して送り返すためのものです。そこにはいくつかのがありますが、実際に行われていることにそれを利用しているわけではありません。

リソースにカスタムメソッドを設定しても問題ありませんが、OOTBに搭載されている優れた機能を見逃したくはありません。

EDIT:私はもともとこれについて十分に説明したとは思いませんが、$resourceはリターンに関していくつかのファンキーなことをします。 Todo.get()およびTodo.query()は両方ともリソースオブジェクトを返しおよびそれをコールバックに渡しますgetが完了したとき$save()コールバックが実際に起動する前にget()を呼び出すことができるという意味で、舞台裏での約束を巧妙に組み合わせて実行しています。リソースをpromise then()またはコールバックメソッドの中で扱うことがおそらく最善です。

標準的な使い方

var Todo = $resource('/api/1/todo/:id');

//create a todo
var todo1 = new Todo();
todo1.foo = 'bar';
todo1.something = 123;
todo1.$save();

//get and update a todo
var todo2 = Todo.get({id: 123});
todo2.foo += '!';
todo2.$save();

//which is basically the same as...
Todo.get({id: 123}, function(todo) {
   todo.foo += '!';
   todo.$save();
});

//get a list of todos
Todo.query(function(todos) {
  //do something with todos
  angular.forEach(todos, function(todo) {
     todo.foo += ' something';
     todo.$save();
  });
});

//delete a todo
Todo.$delete({id: 123});

同様に、OPに投稿したものの場合は、リソースオブジェクトを取得してから、その上に任意のカスタム関数を呼び出すことができます(理論上)。

var something = src.GetTodo({id: 123});
something.foo = 'hi there';
something.UpdateTodo();

私が行って自分のものを発明する前に、私はOOTB実装を試してみました。 $resourceのデフォルトの機能を使っていないのなら、おそらく$httpを自分で使うべきでしょう。

更新:Angular 1.2と約束

Angular 1.2以降、リソースは約束をサポートします。しかし、彼らは他の振る舞いを変えませんでした。

$resourceでpromiseを活用するには、戻り値に$promiseプロパティを使用する必要があります。

約束を使用した例

var Todo = $resource('/api/1/todo/:id');

Todo.get({id: 123}).$promise.then(function(todo) {
   // success
   $scope.todos = todos;
}, function(errResponse) {
   // fail
});

Todo.query().$promise.then(function(todos) {
   // success
   $scope.todos = todos;
}, function(errResponse) {
   // fail
});

$promiseプロパティは、上で返されていたのと同じ値を持つプロパティであることを忘れないでください。だからあなたは奇妙になることができます:

これらは同等です

var todo = Todo.get({id: 123}, function() {
   $scope.todo = todo;
});

Todo.get({id: 123}, function(todo) {
   $scope.todo = todo;
});

Todo.get({id: 123}).$promise.then(function(todo) {
   $scope.todo = todo;
});

var todo = Todo.get({id: 123});
todo.$promise.then(function() {
   $scope.todo = todo;
});
210
Ben Lesh

あなただけの$scope.todo = Todo.get({ id: 123 })を行うことができます。リソース上の.get().query()はすぐにオブジェクトを返し、(テンプレートを更新するために)後で約束の結果で埋めます。これはではない典型的な約束であり、呼び出しの後に実行したい特別なコードがある場合はコールバックまたは$ promiseプロパティを使用する必要があります。ただし、テンプレートでのみ使用している場合は、コールバックでそれをスコープに割り当てる必要はありません。

0
William B