将角度控制器重构为单独的工厂和控制器

时间:2018-01-17 13:28:43

标签: javascript angularjs http dependency-injection angular-promise

学习角度。立即与1.6.6合作。

在我最初的尝试中,我将所有$http请求放入我的控制器中,所以我试图将其从控制器中拉出来并进入工厂以获得更多可重用的代码。我认为我遗漏了与Promise或注入相关的内容,但我的$http调用中的数据未正确绑定到$scope

I've been following along this guide.

我有一个模板,它从控制器开始加载(模板加载正常):

<form ng-init="getAllRegions()" ng-submit="getRandomTown()">

        <h3>Generate Random Town</h3>

        <div class="form-group-row">
            <label for="selectRegion">Select Region:</label>

            <select name="nameEntity"
                id="selectRegion"
                ng-model="guidEntity" 
                ng-options="item.guidEntity as item.nameEntity for item in regions">

                <option value="" ng-if="!guidEntity"></option>
            </select>
        </div>                                  
    </form>

正在调用ng-init函数,并通过控制器和服务。在chrome检查器中,我可以看到数据正确地通过,但我是新手Promises,所以我一路上都失去了一些东西。当$http调用在控制器中正确并且数据绑定到控制器中的$scope时,这一切都按预期工作。

控制器:

angular.
    module('randomTown.controller', []).

    component('randomTownGenerator', {

        templateUrl: 'js/components/randomTownGenerator/randomTownGenerator.tpl.html'

    }). 

    controller('RandomTownCtrl',

        function($scope, randomTownFactory) {

            $scope.data = {};

            $scope.getAllRegions = function () {
                $scope.regions = randomTownFactory.getAllDBRegions();
            }


        }
    );  

服务:

angular.
    module('randomTown.service', []).
    factory('randomTownFactory', function ($q, $http) {

        var service = {};

        service.getAllDBRegions = function() {

            var deferred = $q.defer();

            $http({
                  method: 'GET',
                  url: '/all-regions'
            }).then(function success(data) {
                deferred.resolve(data);
            }), function error(response) {
                deferred.reject('There was an error');
            }

            return deferred.promise;
        }

        return service;
    }); 

2 个答案:

答案 0 :(得分:1)

无需使用$q.defer制作承诺。只需返回$http承诺:

app.factory('randomTownFactory', function ($q, $http) {

    var service = {};

    service.getAllDBRegions = function() {

        ̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶

        ̲r̲e̲t̲u̲r̲n̲ $http({
              method: 'GET',
              url: '/all-regions'
        }).then(function success( ̶d̶a̶t̶a̶ response) {
            ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶s̶o̶l̶v̶e̶(̶d̶a̶t̶a̶)̶;̶
            return response.data;
        }),̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶e̶r̶r̶o̶r̶(̶r̶e̶s̶p̶o̶n̶s̶e̶)̶ ̶{̶

           ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶j̶e̶c̶t̶(̶'̶T̶h̶e̶r̶e̶ ̶w̶a̶s̶ ̶a̶n̶ ̶e̶r̶r̶o̶r̶'̶)̶;̶
        ̶}̶
          ̶r̶e̶t̶u̶r̶n̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶p̶r̶o̶m̶i̶s̶e̶;̶, 
    }

    return service;
}); 

另请注意,success处理程序未显示data。它显示了一个response对象,其中data是其中一个属性。

控制器:

app.controller('RandomTownCtrl',

    function($scope, randomTownFactory) {

        $scope.getAllRegions = function () {
            var promise = randomTownFactory.getAllDBRegions();
            promise.then(function(data) {
                $scope.regions = data;
            }).catch(function(errorResponse) {
                console.log("ERROR", errorResponse.status)
            });          
        }

    }
);  

有关详细信息,请参阅

答案 1 :(得分:0)

试试这个:

$scope.getAllRegions = function () {
            randomTownFactory.getAllDBRegions()
            .then((regions) => {$scope.regions = regions});
        }

原因:因为etAllDBRegion s返回一个承诺,所以你必须使用then属性来获得结果