angular $ scope。$ watch,带有一个返回promise的函数

时间:2014-07-18 13:14:31

标签: angularjs

我正在尝试设置一个关于异步函数的返回值的监视,但是继续运行到无限的摘要循环中。这是我的$ watch

  $scope.$watch(function(){
    var friendsCount = PublicUserData().then(function(data){
      console.log(data.length);
      return data.length;
    });
    return friendsCount;
  }, function(newValue, oldValue) {
    console.log("change"+ newValue);
  });

我可以在chrome控制台中看到两个console.log被调用,但第二个(在回调上)被调用的次数远远超过第一个。

PublicUserData使用$q

.factory('PublicUserData', function($http, $q){
  return function(){
    var defer = $q.defer();
    $http.get('/api/v1/users/').then(function(data){
      defer.resolve(data.data.users);
    })
    return defer.promise;
  }
})

我尝试了一些方法,例如将监视表达式设置为$watch之外的$ scope,但最终返回工厂的代码,而不是工厂的返回值。

是否可以将$watch与实现承诺的函数一起使用?或者我应该使用其他东西吗?

3 个答案:

答案 0 :(得分:6)

你真的真的不想做$watch的AJAX请求。真。

Angular使用脏检查,$watch上的任何内容每次发生变化时都会重复调用$scope函数。如果你可以让它工作,它会在垃圾邮件服务器时完全破坏你的应用程序的性能。

看起来你要做的就是有一个计数器或显示有多少朋友登录的东西?使用服务器事件或轮询机制可以更好地解决这个问题,轮询是最容易实现的。

请考虑这样的事情:

$interval(function() {
    PublicUserData().then(function(data) {
        $scope.data.friendsCount = data.length;
    });
}, 1000);

这将每秒轮询服务器(这可能是过度杀伤,但远不如在$watch中尝试这样做),并使用正确的值更新$scope

答案 1 :(得分:2)

如果你已经有一个承诺,为什么要看$?

PublicUserData().then(function(data){
  $scope.friendsCount = data
});

如果你需要以间隔运行它,最佳性能会给出$ timeout

callForFriendsCount = function () {
  PublicUserData().then(function(data){
    $scope.friendsCount = data
    $timeout(callForFriendsCount, 1000)
  });
}

$ timeout是一个区间更好的想法,因为如果在任何情况下,旧呼叫将花费超过1000毫秒,它将重叠最新的呼叫,使用$ timeout你将避免这个

答案 2 :(得分:2)

为ivarni的优秀答案提供另一个类似的解决方案。如果要轮询(无论是使用超时还是间隔),可以在工厂中执行此操作,只需使用简单的范围变量:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, PublicUserData) {

  $scope.pollData = PublicUserData.pollData;

});


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


  var srv = {
    pollFn: function() {
      srv.stopInterval = $interval(function() {

        srv.pollData.friendCount++;
        console.log('polled');

      }, 1000);
    },
    pollData: {friendCount: 0, other: {}},
    stop: function() {
       $interval.cancel(srv.stopInterval);
    }

  }

  srv.pollFn();

   return srv; 
});

演示:http://plnkr.co/edit/0467sypyeg0Wpdr4302k?p=preview