如何知道Angular.js摘要周期何时开始(或完成)?

时间:2014-01-06 12:08:59

标签: angularjs

我有一个Angular.js应用程序,它在复杂的对象模型中执行大量的会计类型计算(收入,成本,利润等)。对对象模型的任何部分的更改都需要重新执行所有计算。此外,对象模型的许多更改都可以使用绑定直接从我的模板中进行 - 不需要控制器来中间。

许多计算结果都需要显示给用户有助于下游计算。例如,收入显示给用户,但也用于计算利润(也显示给用户)。但是,在每个摘要周期计算收入两次(这是一个复杂的计算)是没有意义的,所以一个明显的优化是在第一次计算时记忆,然后在周期的持续时间内重复使用这个记忆值。

问题是我需要在摘要周期的开头或结尾清除这些记忆。一种方法是控制器拦截每个可能的变化源,并在继续计算之前手动取消对象模型。相反,我更喜欢继续使用已经设置的绑定。

据我所知,我需要的是一种了解摘要周期何时开始或何时完成的方法。当我收到此通知时,我可以重置备忘录。

Angular $watch documentation说:

  

如果您想在每次调用$ digest时收到通知,您可以   注册一个没有监听器的watchExpression函数。 (以来   当a表示每个$ digest周期时,watchExpression可以多次执行   检测到更改,准备好多次调用听众。)

这对我没用,因为在摘要周期的每次迭代中清除memoizations会破坏首先使用它们的目的。我每个摘要周期只需要一个通知。

我该怎么做,还是有其他方法来解决问题?

1 个答案:

答案 0 :(得分:10)

好吧,我想我终于搞清楚了,所以我想回答我自己的问题。

有一个名为$$postDigest的私有Angular方法,它将在下一个摘要周期结束后回调函数。但是,它只运行一次,如果你试图让它以递归的方式重新安排它,它会进入无限循环。

要解决此问题,您可以将$$postDigest与常规$watch结合使用。如果你有一个名为fn的函数,你希望控制器在每个摘要周期后调用,你可以在控制器函数中添加这样的函数:

...
var hasRegistered = false;
$scope.$watch(function() {
  if (hasRegistered) return;
  hasRegistered = true
  // Note that we're using a private Angular method here (for now)
  $scope.$$postDigest(function() {
    hasRegistered = false;
    fn();
  });
});
...

这基于a code fragment by Karl Seamon。显然,在$scope上调用私有方法并不理想。希望这些行中的$postDigestWatch方法最终可能会添加到Angular中。

关于我原来的问题的评论中有一些混淆,关于你为什么要这样做:如果你还不清楚,请查看this blog post I wrote涵盖了我的特定用例。