【问题标题】:AngularJS: $eval takes much timeAngularJS:$eval 需要很多时间
【发布时间】:2015-07-29 08:59:48
【问题描述】:

在分析我的 angularjs 应用程序时,我发现有时$get.Scope.$eval 需要超过 100 毫秒。在单个 $digest 循环中,至少有 3 个很长的 $get.Scope.$eval 案例,我想优化这部分。

在分析器中的 $get.Scope.$eval 下方,我只看到调用 angularjs 代码。

这是个人资料图表的屏幕截图。

任何人都可以建议,发生了什么以及如何优化这部分?我想这可能是由ng-repeatng-includeng-if 引起的,但我不确定。

更新: 这是我的application 的简化结构。可能问题出在我的应用程序的体系结构中。该应用程序主要在单个路由上工作并且仅在 3 种情况下更改它,因此应用程序将状态存储在全局控制器 AppController - 胖控制器中。 html 中还有 20k+ 个节点,并且数量可以增长(我看到的最大是 60k)

【问题讨论】:

    标签: javascript angularjs performance


    【解决方案1】:

    $eval 在解析角度表达式时由 angular 内部使用,例如{{variable}}。在没有看到任何代码的情况下,很难分辨出哪些表达式不必要地使用了资源,但通常太大或嵌套的ng-repeats(或ng-repeat 中包含的许多ng- 指令)是代码异味。

    Angular 使用脏检查来评估这些表达式(因为没有更好的选择)——这意味着每次使用 {{}} 语法创建绑定时,它都会创建一个隐式 $watch 表达式来获取该值,这将是调用每个摘要循环以查看值是否已更改(在更改时重新生成 DOM 的相关部分)。

    这是我过去成功使用的一项优化:

    大多数情况下,当您使用{{}} 绑定一个值时,您实际上并不期望该值会发生变化(如标签),而这种双向数据绑定完全是多余的。从 Angular 1.3 版开始,您可以使用 :: 语法选择 create one-time bindings

    一次性表达式一旦稳定就会停止重新计算,如果表达式结果是非未定义值,则在第一次摘要之后发生这种情况

    这消除了此类绑定的相应性能开销。 (如果您使用的是较旧的 Angular 版本,外部库可以模仿这种行为,例如 bindonce。)

    以下是我在分析/优化 Angular 应用时发现的一些有用的附加工具:

    • Batarang,一个 chrome 扩展“用于调试和分析 Angular 应用程序”
    • This stackoverflow answer,提供了一个简洁的解决方案,用于计算页面上活跃的观看表达式的数量。一个经验法则是,如果你超过 2000,你会开始注意到性能问题,你应该考虑改变你的架构——使用延迟加载机制,重新考虑你是否真的需要所有的绑定等等。

    • 在生产环境中,disabling the default "debug mode" of angular 也有助于提高性能。

    【讨论】:

    • 谢谢!不幸的是,我已经使用 and 和 :: 和batarang 并试图减少观察者的数量。我的观察者不到 2k,而且应用程序非常缓慢。可能我使用的架构是错误的,但这是另一个问题。
    • 架构方面,我有很多ng-ifng-showng-repeat,没有改变路线。在每个用户的操作之后,我所有的 300 多个范围都需要被消化。可能$eval 试图评估很多我嵌套的ng-include,但我不知道并试图用我的问题来理解它
    • 300 多个活动范围听起来像是一场噩梦,无论是性能还是可维护性。你确定你同时需要所有这些吗?你能给我们一些更复杂的嵌套结构的代码示例吗?
    • 当然,但这可能是一个比当前更常见的问题。稍后我会添加代码结构的sheme
    • 这里是代码的简化结构gist.github.com/havenchyk/c1c668de6bc112ea93f2#file-code-md我只更改了3种情况下的路由,所以主要是全局控制器中的应用程序存储状态AppCtrl
    猜你喜欢
    • 2020-03-19
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 2011-10-02
    • 2021-01-11
    • 2014-08-16
    相关资源
    最近更新 更多