Watch promise (resource) changes in Angular 1.2.0+

2019-06-03 15:13发布

问题:

I'm using $resource for loading array of items in my controller:

$scope.items = api.items.query();

The $scope.items is now promise. Once it is resolved, it contains array of items. Than I have some methods, manipulating the items, for example:

// template
<div ng-repeat="item in items">
    <a href="" ng-click="doSomething(item)">Do it!</a>
</div>

// controller:
$scope.doSomething = function(item) {
    item.$doSomething(); // the items 
};

Here I would like to watch changes in $scope.items, so it gets notified once any of the item changes . I tried this:

$scope.$watch($scope.items, function() {
    console.log('changed');
});

but this doesn't work - it is not triggered after the doSomething changes the object. Neither helps the third objectEquality parameter. I also tried $watchCollection, but with no luck.

I found this worked for a short period of time - since Angular 1.2.rc2 the promises unwraping was introduced (https://github.com/angular/angular.js/issues/3503), but it was removed in 1.2.0 (https://github.com/angular/angular.js/issues/4158).

So is there now (current stable is Angular 1.2.4) any way how to do this?

Thanks!

P.S.: This was also discussed in this question: AngularJS - binding/watching a function which returns a promise, but this is not applicable for 1.2.0+.

回答1:

Don't assign the Promise to $scope.items, wait until the promise resolves then assign the result to $scope.items.

api.items.query().then(function(itemsQueryResults){
  $scope.items = itemsQueryResults;
});

When the items property is updated Angular will run a digest cycle as normal and your ng-repeat will populate.



回答2:

In Angular 1.4.6, I was able to solve this by adding a third parameter to $watch. Note that I also had to reference the scope property by string name:

$scope.$watch('items', function() {
    console.log('changed');
}, true);