Exemple de ressource RESTful AngularJS $

145

Je voudrais utiliser $ resource pour appeler mon service Web RESTful (sur lequel je travaille toujours) mais j'aimerais savoir si mon script AngularJS est correct en premier.

Le todo DTO a: {id, order, content, done}

:cmdest donc je peux appeler api/1/todo/resetpour effacer la table todo dans la base de données.

Voici le code avec commentaire de ma compréhension:

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

Une chose en particulier dont je ne suis pas sûr est la méthode PATCH, je ne veux pas tout mettre à jour, puis-je mettre à jour un seul champ? Suis-je en train de construire correctement ce morceau de code?

À M
la source
2
Il semble que vous utilisiez $ resource comme service $ http de base. $ resource sert davantage à récupérer un objet à partir d'une source de données RESTful, à le manipuler, puis à le renvoyer avec obj.save(). Vous pouvez faire ce que vous essayez de faire avec une implémentation basique de $ http.
Ben Lesh
4
@blesh pourquoi ne devrait-il pas utiliser $ resource quand il veut communiquer avec son webservice RESTful? Comme vous l'avez dit, n'est-ce pas exactement le but?
F Lekschas
Il me cherche mais je définirais la ressource $ comme un service et l'injecterais. Cela vous permet de le réutiliser facilement ailleurs plus tard, si vous en avez besoin.
F Lekschas
4
@Flek Eh bien, il peut utiliser $ resource comme $ http s'il le souhaite . Mais ce n'est pas vraiment comme ça qu'il était censé être utilisé.
Ben Lesh
3
Eh bien, ce n'est pas vraiment un "problème", à proprement parler. C'est plus qu'il ne tire aucun avantage de l'API RESTful et de tout ce que $ resource peut faire pour vous dès la sortie de la boîte.
Ben Lesh

Réponses:

211

$ resource était destiné à récupérer les données d'un point de terminaison, à les manipuler et à les renvoyer. Vous en avez une partie , mais vous n'en tirez pas vraiment parti pour ce pour quoi il a été conçu.

C'est bien d'avoir des méthodes personnalisées sur votre ressource, mais vous ne voulez pas manquer les fonctionnalités intéressantes fournies avec OOTB.

EDIT : Je ne pense pas avoir expliqué cela assez bien à l'origine, mais $resourcefait des trucs géniaux avec des retours. Todo.get()et les Todo.query()deux renvoient l'objet de ressource et le transmettent au rappel pour une fois la récupération terminée. Il fait des choses fantaisistes avec des promesses dans les coulisses qui signifient que vous pouvez appeler $save()avant que le get()rappel ne se déclenche réellement, et il attendra. Il est probablement préférable de traiter votre ressource à l'intérieur d'une promesse then()ou de la méthode de rappel.

Utilisation standard

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

De même, dans le cas de ce que vous avez publié dans l'OP, vous pouvez obtenir un objet ressource, puis appeler l'une de vos fonctions personnalisées dessus (théoriquement):

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

J'expérimenterais l'implémentation OOTB avant d'aller inventer la mienne. Et si vous constatez que vous n'utilisez aucune des fonctionnalités par défaut de $resource, vous devriez probablement l'utiliser $httpseule.

Mise à jour: Angular 1.2 et promesses

Depuis Angular 1.2, les ressources prennent en charge les promesses. Mais ils n'ont pas changé le reste du comportement.

Pour tirer parti des promesses avec $resource, vous devez utiliser la $promisepropriété sur la valeur renvoyée.

Exemple utilisant des promesses

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

Gardez simplement à l'esprit que la $promisepropriété est une propriété sur les mêmes valeurs qu'elle renvoyait ci-dessus. Vous pouvez donc devenir bizarre:

Ce sont équivalents

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
la source
1
Je suppose que je vais affiner ma déclaration comme ceci: si vous n'utilisez aucune fonctionnalité OOTB de $ resource, alors vous prenez simplement de la mémoire avec des références d'objets et de fonctions dont vous n'avez pas besoin. Cela va-t-il blesser quelque chose? Probablement pas. Mais il peut être plus efficace d'utiliser simplement $ http si vous ne faites que des opérations CRUD standard et ne tirez pas parti des fonctionnalités de $ resources neato.
Ben Lesh
5
Blesh, y a-t-il des documents qui traitent de la fonctionnalité OOTB? Les documents angulaires sont déroutants.
erichrusch
9
Malheureusement, il n'y en a pas vraiment. Je viens de fouiller dans leur source sur GitHub.
Ben Lesh
2
Ne Todo.get({id: 123});retourne pas une promesse et pas un objet direct?
Ingó Vals
1
Peut-être pouvez-vous m'aider avec ma question: stackoverflow.com/questions/30405569/… .
AJ_83
0

vous pouvez simplement le faire $scope.todo = Todo.get({ id: 123 }). .get()et .query()sur une Ressource, renvoyez un objet immédiatement et remplissez-le avec le résultat de la promesse plus tard (pour mettre à jour votre modèle). Ce n'est pas une promesse typique, c'est pourquoi vous devez utiliser un callback ou la propriété $ promise si vous avez un code spécial que vous souhaitez exécuter après l'appel. Mais il n'est pas nécessaire de l'attribuer à votre étendue dans un rappel si vous ne l'utilisez que dans le modèle.

Guillaume B
la source