我有一个Angular.js应用程序,它在复杂的对象模型中执行大量的会计类型计算(收入,成本,利润等)。对对象模型的任何部分的更改都需要重新执行所有计算。此外,对象模型的许多更改都可以使用绑定直接从我的模板中进行 - 不需要控制器来中间。
许多计算结果都需要显示给用户,有助于下游计算。例如,收入显示给用户,但也用于计算利润(也显示给用户)。但是,在每个摘要周期计算收入两次(这是一个复杂的计算)是没有意义的,所以一个明显的优化是在第一次计算时记忆,然后在周期的持续时间内重复使用这个记忆值。
问题是我需要在摘要周期的开头或结尾清除这些记忆。一种方法是控制器拦截每个可能的变化源,并在继续计算之前手动取消对象模型。相反,我更喜欢继续使用已经设置的绑定。
据我所知,我需要的是一种了解摘要周期何时开始或何时完成的方法。当我收到此通知时,我可以重置备忘录。
Angular $watch documentation说:
如果您想在每次调用$ digest时收到通知,您可以 注册一个没有监听器的watchExpression函数。 (以来 当a表示每个$ digest周期时,watchExpression可以多次执行 检测到更改,准备好多次调用听众。)
这对我没用,因为在摘要周期的每次迭代中清除memoizations会破坏首先使用它们的目的。我每个摘要周期只需要一个通知。
我该怎么做,还是有其他方法来解决问题?
答案 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涵盖了我的特定用例。