Quelle est la meilleure pratique pour effectuer un appel AJAX dans Angular.js?

Je lisais cet article: http://eviltrout.com/2013/06/15/ember-vs-angular.html

Et ça dit,

En raison de l’absence de conventions, je me demande combien de projets Angular reposent sur de mauvaises pratiques telles que les appels AJAX directement dans les contrôleurs. En raison de l’dependency injection, les développeurs injectent-ils des parameters de routeur dans des directives? Les développeurs novices d’AngularJS vont-ils structurer leur code d’une manière qui, selon un développeur expérimenté d’AngularJS, est idiomatique?

Je suis en train $http faire des appels $http partir de mon contrôleur Angular.js. Pourquoi est-ce une mauvaise pratique? Quelle est la meilleure pratique pour faire des appels $http alors? et pourquoi?

EDIT: Cette réponse était principalement axée sur la version 1.0.X. Pour éviter toute confusion, il est modifié pour refléter la meilleure réponse pour TOUTES les versions actuelles d’Angular à compter d’aujourd’hui, 2013-12-05.

L’idée est de créer un service qui renvoie une promesse aux données renvoyées, puis de l’appeler dans votre contrôleur et de tenir la promesse de remplir votre propriété $ scope.

Le service

 module.factory('myService', function($http) { return { getFoos: function() { //return the promise directly. return $http.get('/foos') .then(function(result) { //resolve the promise as the data return result.data; }); } } }); 

Le controlle:

Manipulez la méthode then() la promesse et extrayez les données. Définissez la propriété $ scope et faites tout ce que vous pourriez avoir à faire.

 module.controller('MyCtrl', function($scope, myService) { myService.getFoos().then(function(foos) { $scope.foos = foos; }); }); 

Résolution de promesse intégrée (1.0.X uniquement):

Dans Angular 1.0.X, la cible de la réponse originale ici, les promesses recevront un traitement spécial de la part de View. Lorsqu’ils résolvent, leur valeur résolue sera liée à la vue. Cela a été déconseillé dans 1.2.X

 module.controller('MyCtrl', function($scope, myService) { // now you can just call it and stick it in a $scope property. // it will update the view when it resolves. $scope.foos = myService.getFoos(); }); 

La meilleure pratique consiste à extraire l’appel $http dans un “service” fournissant des données à votre contrôleur:

 module.factory('WidgetData', function($http){ return { get : function(params){ return $http.get('url/to/widget/data', { params : params }); } } }); module.controller('WidgetController', function(WidgetData){ WidgetData.get({ id : '0' }).then(function(response){ //Do what you will with the data. }) }); 

En résumant cet appel $http vous pourrez réutiliser ce code sur plusieurs contrôleurs. Cela devient nécessaire lorsque le code qui interagit avec ces données devient plus complexe, vous souhaiterez peut-être traiter les données avant de les utiliser dans votre contrôleur et mettre en cache le résultat de ce processus afin de ne pas avoir à le retraiter.

Vous devez considérer le «service» comme une représentation (ou un modèle) des données que votre application peut utiliser.

La réponse acceptée me donnait l’erreur $http is not defined donc je devais le faire:

 var policyService = angular.module("PolicyService", []); policyService.service('PolicyService', ['$http', function ($http) { return { foo: "bar", bar: function (params) { return $http.get('../Home/Policy_Read', { params: params }); } }; }]); 

La principale différence étant cette ligne:

 policyService.service('PolicyService', ['$http', function ($http) { 

J’ai mis une réponse pour quelqu’un qui voulait un service Web totalement générique dans Angular. Je vous recommande simplement de le twigr et il s’occupera de tous vos appels de service Web sans avoir à les coder tous vous-même. La réponse est ici:

https://stackoverflow.com/a/38958644/5349719