我正在尝试设置一个关于异步函数的返回值的监视,但是继续运行到无限的摘要循环中。这是我的$ 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
与实现承诺的函数一起使用?或者我应该使用其他东西吗?
答案 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;
});