Какова наилучшая практика для вызова AJAX в Angular.js?

Я читал эту статью: http://eviltrout.com/2013/06/15/ember-vs-angular.html

И он сказал:

Из-за отсутствия соглашений, интересно, сколько проектов Angularполагаться на плохие практики, такие как AJAX-вызовы непосредственно внутри контроллеров? Из-за инъекции зависимости, разработчики вводят роутер параметры в директивы? Являются ли начинающие разработчики AngularJS структурировать свой код таким образом, чтобы опытный разработчик AngularJS считает, что идиоматический?

Я действительно звоню $http из моего контроллера Angular.js. Почему это плохая практика? Какова наилучшая практика для создания вызовов $http? и почему?

Ответ 1

EDIT: этот ответ был в основном сосредоточен на версии 1.0.X. Чтобы предотвратить путаницу, он изменяется, чтобы отобразить лучший ответ для ВСЕХ текущих версий Angular на сегодняшний день, 2013-12-05.

Идея заключается в создании службы, которая возвращает обещание возвращенным данным, а затем вызывает это в вашем контроллере и обрабатывает обещание там заполнить ваше свойство $scope.

Сервис

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

Контроллер:

Обработать метод обещания then() и получить данные из него. Задайте свойство $scope и сделайте все, что вам может понадобиться.

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

Разрешение Promise в режиме просмотра (только 1.0.X):

В Angular 1.0.X, цель первоначального ответа здесь, promises, получит вид View. Когда они разрешат, их разрешенная ценность будет привязана к виду. Это устарело в 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();
});

Ответ 2

Лучшей практикой было бы абстрактное обращение $http к "службе", которая предоставляет данные вашему контроллеру:

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

Тестирование вызова $http, как это, позволит вам повторно использовать этот код для нескольких контроллеров. Это становится необходимым, когда код, который взаимодействует с этими данными, становится более сложным, возможно, вы хотите обработать данные перед его использованием в своем контроллере и кэшировать результат этого процесса, чтобы вам не пришлось тратить время на его повторную обработку.

Вы должны думать о "службе" как о представлении (или модели) данных, которое может использовать ваше приложение.

Ответ 3

Принятый ответ дал мне ошибку $http is not defined, поэтому мне пришлось это сделать:

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

Основное отличие этой строки:

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

Ответ 4

Я поставил ответ для тех, кто хотел получить полностью общий веб-сервис в Angular. Я бы порекомендовал просто подключить его, и он позаботится обо всех ваших вызовах веб-сервисов, не заставляя их кодировать самостоятельно. Ответ здесь:

fooobar.com/info/41964/...