How can I get a deferred object set in one scope to be included in the digest of another scope in AngularJS?

StackOverflow https://stackoverflow.com/questions/13500051

質問

Folks, I have a problem. I'm using AngularJS and I am setting up a deferred object inside an Angular service definition:

angular.module('myServices', []).
  service('Brand', function($rootScope, $q){
    var service = {
        getNext: function() {
            var deferred = $q.defer();

            setTimeout(function() {
                deferred.resolve('foo');
            }, 2000);

            return deferred.promise;
        }
    };

    return service;
});

The service is used in my controller:

angular.module({
    controllers: {
        brand: function($scope, Brand) {
            $scope.changeBrand = function() {
                $scope.brand = Brand.getNext();
            }
        }
    }
}, ['myServices]);

And finally the view waits for the promise to be resolved and then displays it:

<a ng-click="changeBrand()" id="changeBrand">Change</a>
<p ng-bind="brand"></p>

The trouble is that although the promise is being resolved and although the view does just fine waiting for the promise to be resolved and showing the result, it doesn't do it immediately. It only shows up when I add this code and click the link:

// View:
<a ng-click="apply()">Apply</a> 

// Controller:
$scope.apply = function() {
    $scope.$apply();
};

Does the part of the digest that the promise lives in exist separately from the digest that runs when the view/controller's scope is changed? How can I get the digest to run on the view/controller's scope automatically when the deferred resolves?

Thanks!

役に立ちましたか?

解決

Few days ago I had the same issue while implementing lazy controllers with promisses. When you take a look at the documentation about routeProvider there is a sample that uses $timeout service with promises (https://github.com/angular/angular.js/blob/master/src/ng/route.js#L186). $timeout implemation uses $rootScope.$apply() to call the lifecycle and refresh the bindings (AFAIK it calls all dirty check functions - it's how bindings work in Angular). So the solution to my problem (and I think also yours) was adding $rootScope.$apply() after the resolve(), like this:

 setTimeout(function() {
            deferred.resolve('foo');
            $rootScope.$apply();
        }, 2000);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top