如何在AngularJS摘要循环中处理观察者和过滤器?

时间:2013-10-16 03:14:30

标签: angularjs angularjs-scope angularjs-filter

据我所知,范围观察者和过滤器都在摘要循环中重复执行。但是以下内容对我来说有点不清楚:

  • 它们是否执行了相同数量的循环?

  • 是否都是由相同情况触发的?

1 个答案:

答案 0 :(得分:7)

每个摘要周期都会检查手表。 $watch可以观看Angular expression。在表达式中,可以有一个filter Angular必须评估(使用$interpolate)来判断监视的表达式是否已经改变。

是否都是由相同情况触发的?

因此,过滤器不是由$digest直接运行,而是由$watch运行。实际上,过滤器是由观察表达式的评估触发的。

有关过滤器在$digest的性能方面特别谈到的原因有几个。看看这两个表达式:

表达式1:{{searchText+2}}

表达式2:{{searchText | myFilter:true}}

每次触发$digest时都会评估两个表达式。因此,一个风险区域就是myFilter可能很复杂,最终使用的处理器周期比简单的处理器周期多(如上面的+2)。

稍微不那么明显,如果过滤器不是幂等的,那么过滤器会导致所有观察者的额外运行。在$digest的每次运行中,如果任何手表导致更改,则设置脏位。如果设置了脏位,它会再次重新运行所有手表。这允许传播任何更改。例如,如果其中一个手表更改searchText,那么Angular需要让所有其他观察者有机会查看其结果是否取决于searchText,因此应该更改。

这就是上面的表达式1和2之间的区别。最糟糕的情况是,myFilter会返回一个随机数。 $digest运行,在评估监视时看到更改(过滤器的上一个结果与新结果不匹配),因此它再次运行监视列表。由于过滤器返回一个随机数,因此结果很可能已更改,从而触发另一次$digest次运行。等等...... Angular在通过它的观察列表进行10次循环之后有一个内置的停止 - 它表示如果结果在10次尝试之后没有稳定则出现问题,因此它会放弃投掷“错误:10 $ digest()迭代到了。中止!“

它们的执行周期是否相同?

因此每个观看的表达式(包括任何过滤器)至少每$digest 运行两次。一旦因为触发$digest的更改而再次检查该结果是否需要传播。如果该传播导致任何更改,那么手表和过滤器将再次运行,直到没有任何变化。

当然,如果多个观察的表达式使用相同的过滤器,那么对于每个表达式,将按照上述方式运行该过滤器。