Przykład RESTful zasobów AngularJS $

145

Chciałbym użyć $ resource, aby wywołać moją usługę sieciową RESTful (nad którą nadal pracuję), ale chciałbym się dowiedzieć, czy mój skrypt AngularJS został najpierw poprawny.

Todo DTO ma: {id, order, content, done}

:cmdjest tak, że mogę zadzwonić, api/1/todo/resetaby wyczyścić tabelę zadań do wykonania w bazie danych.

Oto kod z komentarzem mojego zrozumienia:

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();
}

Jedną z rzeczy, których nie jestem pewien, jest metoda PATCH, nie chcę aktualizować wszystkiego, czy mogę zaktualizować tylko jedno pole? Czy poprawnie tworzę ten fragment kodu?

Tomek
źródło
2
Wygląda na to, że używasz $ resource jako podstawowej usługi $ http. $ resource służy raczej do pobierania obiektu ze źródła danych zgodnego z REST, manipulowania nim, a następnie wysyłania go z powrotem obj.save(). Możesz zrobić to, co próbujesz zrobić z podstawową implementacją $ http.
Ben Lesh
4
@blesh, dlaczego nie miałby używać $ resource, gdy chce komunikować się ze swoją usługą internetową RESTful? Jak powiedziałeś, czy nie jest to dokładnie celem tego?
F Lekschas
Szuka mnie, ale zdefiniowałbym zasób $ jako usługę i wstrzyknąłbym go. Dzięki temu możesz łatwo użyć go później w innym miejscu, jeśli zajdzie taka potrzeba.
F Lekschas
4
@Flek Cóż, jeśli chce , może użyć zasobu $, takiego jak $ http . Ale tak naprawdę nie miało to być używane.
Ben Lesh
3
Cóż, to naprawdę nie jest „problem”, na przykład. Co więcej, nie korzysta z RESTful api i wszystkich rzeczy, które $ resource może dla Ciebie zrobić po wyjęciu z pudełka.
Ben Lesh

Odpowiedzi:

211

$ resource miał na celu pobieranie danych z punktu końcowego, manipulowanie nimi i wysyłanie ich z powrotem. Masz tam trochę tego, ale tak naprawdę nie wykorzystujesz tego do tego, do czego został stworzony.

Dobrze jest mieć niestandardowe metody w swoim zasobie, ale nie chcesz przegapić fajnych funkcji, które oferuje OOTB.

EDYCJA : Myślę, że początkowo nie wyjaśniłem tego wystarczająco dobrze, ale robię $resourcetrochę funky ze zwrotami. Todo.get()i Todo.query()oba zwracają obiekt zasobu i przekazują go do wywołania zwrotnego po zakończeniu pobierania. Robi kilka wymyślnych rzeczy z obietnicami za kulisami, co oznacza, że ​​możesz zadzwonić, $save()zanim wezwanie get()zwrotne faktycznie zostanie uruchomione , i będzie czekać. Prawdopodobnie najlepiej jest zająć się zasobem w ramach obietnicy then()lub metody wywołania zwrotnego.

Standardowe zastosowanie

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});

Podobnie, w przypadku tego, co opublikowałeś w PO, możesz pobrać obiekt zasobu, a następnie wywołać na nim dowolną ze swoich funkcji niestandardowych (teoretycznie):

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

Eksperymentowałem z implementacją OOTB, zanim poszedłem i wymyśliłem własną. A jeśli okaże się, że nie używasz żadnej z domyślnych funkcji programu $resource, prawdopodobnie powinieneś używać $httpgo samodzielnie.

Aktualizacja: Angular 1.2 i Promises

Począwszy od Angular 1.2, zasoby obsługują obietnice. Ale nie zmienili reszty zachowania.

Aby wykorzystać obietnice $resource, musisz użyć $promisewłaściwości zwróconej wartości.

Przykład przy użyciu obietnic

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
});

Pamiętaj tylko, że $promisewłaściwość jest właściwością na tych samych wartościach, które zwracała powyżej. Więc możesz stać się dziwny:

Te są równoważne

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;
});
Ben Lesh
źródło
1
Myślę, że sprecyzuję moje oświadczenie w ten sposób: jeśli nie używasz żadnych funkcji OOTB w $ resource, to po prostu zajmujesz pamięć przez odwołania do obiektów i funkcji, których nie potrzebujesz. Czy to coś zrani? Prawdopodobnie nie. Ale może być bardziej wydajne użycie $ http, jeśli wykonujesz tylko standardowe operacje CRUD i nie wykorzystujesz funkcji $ resources neato.
Ben Lesh
5
Blesh, czy są jakieś dokumenty, które omawiają funkcjonalność OOTB? Kątowe dokumenty są mylące.
erichrusch
9
Niestety, tak naprawdę nie ma. Właśnie przekopałem się przez ich źródło na GitHubie.
Ben Lesh
2
Nie Todo.get({id: 123});powrócić obietnicę, a nie prosto w górę obiekt?
Ingó Vals,
1
Być może pomożesz mi z moim pytaniem: stackoverflow.com/questions/30405569/… .
AJ_83
0

możesz po prostu zrobić $scope.todo = Todo.get({ id: 123 }). .get()a .query()na zasobie natychmiast zwróć obiekt i wypełnij go później wynikiem obietnicy (aby zaktualizować szablon). To nie typowy obietnica, dlatego trzeba użyć wywołania zwrotnego lub właściwość $ obietnica, jeśli masz jakiś specjalny kod, który chcesz wykonywany po wywołaniu. Ale nie ma potrzeby, aby przypisać go do swojego zakresu w zwrotnego jeśli tylko używając go w szablonie.

William B.
źródło