我在模板中有一个计时器,它使用angular的$ interval服务每秒更新一次。
var now = moment();
var startActual = moment(scope.vm.start_actual);
var duration = now.diff(startActual);
timer = $interval(function(){
duration = moment.duration(duration + 1000, 'milliseconds');
var d = Math.abs(duration.days());
var h = Math.abs(duration.hours());
var m = Math.abs(duration.minutes());
var s = Math.abs(duration.seconds());
scope.mins = prefix + (d <= 9 ? "0"+d : d) + ':' + (h <= 9 ? "0"+h : h) + ':' + (m <= 9 ? "0"+m : m) + ':' + (s <= 9 ? "0"+s : s);
}, 1000);
我的观点中有{{mins}}。这工作正常,但我刚刚意识到这是每次运行此功能时触发一个摘要循环(每秒)。这个应用程序非常复杂,这似乎是一个巨大的不必要的CPU加载,当我所有更新是一个计时器。我注意到$ interval函数作为一个可选的invokeApply参数,但当我将其设置为false时,计时器根本不会渲染到我的模板。如何设置此计时器以使其每秒更新一次,但不会触发完整的摘要周期?任何帮助将不胜感激!
答案 0 :(得分:4)
$interval
有一个额外的fourth argument可用于此:
timer = $interval(function(){
// Your code here
}, 1000, 0, false);
在这个例子中:
现在,如果您需要其他观察者意识到您已更新mins
变量,那么您肯定需要触发摘要周期。
由于您希望避免这种情况,因此只有将invokeApply
设置为false
并在这种情况下直接操作DOM才能实现最佳性能。
答案 1 :(得分:2)
对于这样一个非常小的一点,我建议使用小指令直接更新元素而不会每秒导致$digest
循环(当你有更大的应用程序时,这可能真的很麻烦。
我很快写了这样的指令
http://plnkr.co/edit/oA0C6ou29hlKZYVhkRNv?p=preview
app.directive('procrastination', function() {
return {
link: function(scope, element) {
var time;
time = 0;
setInterval(function() {
time++;
element.text("You have wasted " + time + "s");
}, 1000);
}
};
});
答案 2 :(得分:0)
Angular仅在摘要中执行更新,因此如果您将invokeApply
$interval
参数设置为false
,您的视图将不会自动更新,正如您已经注意到的那样。
但是,摘要可能不像您想象的那样占用CPU密集度。 Angular的摘要工作方式是它遍历所有范围并检查已注册的手表(内部角度特征,如模板插值也添加手表),将当前值与先前值进行比较。只有当观察到的表达式发生变化时才会进行更新。如果唯一改变的是一个变量,摘要可能只需要几毫秒,即使对于复杂的应用程序也是如此。你可以为自己计时。
var start = +new Date();
$rootScope.$digest();
console.log(+new Date() - start);
如果速度太慢,您只能触发特定范围的摘要,而且它是孩子。在你的情况下
timer = $interval(function() {
...
scope.$digest();
}, 1000, 0, false);
只会对scope
和任何子范围进行摘要,而不是完整的摘要。如果您的CPU密集度最高的手表不在此范围内,这将更快。
请记住,这仅适用于scope.$digest
。 scope.$apply
触发完整摘要(来自$rootScope
)。