【问题标题】:Debugging AngularJS Internet Explorer Lock-up调试 AngularJS Internet Explorer 锁定
【发布时间】:2014-12-01 23:40:59
【问题描述】:

IE10 有一个问题,我可以轻松复制。在我的应用程序中通过几页弹跳后,IE 完全锁定(没有“长时间运行的脚本”警告,只是完全冻结)。我必须从任务管理器中杀死它。我已经禁用了所有附加组件,并且有一个干净的状态。我在一个相当大的工作站(Win7、16GB ram、i7、yadda yadda)上运行。

它不会在 Chrome 或 Firefox 中冻结。只有 IE10 和 IE11。

关于我的应用

我正在与工业控制系统集成以显示我的系统的活动状态。我有很多 XHR 轮询正在进行(将转移到 WebSocket,但现在,这很容易与我的 API 集成)。每 500 毫秒从端点刷新一次数据,这会更新页面上的一堆字段。

当应用程序未冻结时,浏览起来既方便又快捷。找不到导致冻结的任何特定条件。

在任何给定时间,我的应用都有 75 到 400 个 $watches(使用 this answer 计算)。

当前运行 AngularJS v1.3.0-rc.4。在 1.2.25 有类似的锁定。

那么,我的问题

我该如何调试呢?我试过让 F12 开发者工具保持打开状态,但没有任何东西输出到控制台。运行脚本分析器(Batarang 在 IE 中不可用)显示我在 $digest 中每 10 秒花费大约 200 毫秒(含)。接下来我该尝试什么?

【问题讨论】:

  • 也许 Visual Studio 的分析器更好:msdn.microsoft.com/en-us/library/dd264908.aspx
  • 如果您每 500 毫秒轮询一次,那么 $interval 设置/初始化控制器或服务/工厂在哪里? (我知道这与调试没有直接关系,只是一个想法)
  • @Brocco 它位于控制器包含的轮询服务中。 (我只是 $timeout 而不是 $interval 所以我确保在处理响应和开始下一个请求之间保持至少 500 毫秒的间隔)。
  • @MikeGriffith 明白了,因为每次我建议停止对销毁控制器的轮询时都会创建一个新控制器。
  • @Brocco 是的,已经确保这样做(绑定到 $scope $destroy 事件以从轮询中“取消注册”)。谢谢你的主意。我的网络活动看起来完全合理,直到 IE 冻结(此时所有 XHR 活动都停止访问服务器)。

标签: javascript jquery angularjs performance internet-explorer


【解决方案1】:

哎呀,我能感同身受。

你能把关注点分开吗?使用不使用 XHR 的服务模拟来测试您的前端(带有 ng-repeat 的 DOM 部分),看看您是否遇到了同样的问题。您也可以尝试在不将 XHR 服务连接到前端的情况下对其进行测试。 (例如,为了测试目的,您可以有一个只有 <span>{{myDataArray}}</span> 之类的测试视图,以避免 ng-repeat 问题。)基本上,尝试将问题分成两半,看看您是否仍然可以复制问题.

基本上,我的推理是这样的;如果您模拟您的服务并且仍然每 500 毫秒轮询一次,并且您遇到了问题,那么您可能遇到了 IE 的 DOM 更新问题。如果您没有遇到问题,但您测试了真正的服务并且 IE 冻结了,那么 XHR 有问题(可能是您的轮询时间?)或者可能是 Angular 的监视系统问题。

我希望我能在这里提供更多帮助,但这是我要开始的地方。尝试通过剔除一些代码来缩小问题范围。这不会很有趣,但是如果您使用 Angular 的最佳实践(即依赖注入和关注点分离)编写应用程序,那么痛苦就会减少。

TL;DR - “接下来我该尝试什么?”您将不得不开始智能地剔除一些代码,以查看哪些有效,哪些无效。

【讨论】:

  • 我一直在尝试这个,它似乎确实是 DOM 给了最大的麻烦。因此,我删除了所有 ng-repeats 以支持手工制作的 DOM 操作(为 IE 进行去抖动以避免在 Chrome 中尽可能频繁地触摸它)。所以,仍然不完美,但感谢您的提示!
  • @MikeGriffith 对于它的价值,我完全忘记提及这一点 - 但是当您使用 ng-repeat 时,使用 track by 语句通常会很好。这在理论上避免了很多不必要的 DOM 重绘(虽然在实践中,我不知道在某个阈值之后它有多少增益)。真正的问题是 DOM 和摘要循环,因为我理解 ng-repeat 使用了很多手表(除了插值的东西)。
【解决方案2】:

我针对所有 IE 锁定(双关语)的全局解决方案是将有问题的代码封装在 window.setTimeout 中。现在大多数这些问题是由以下原因引起的:

  1. 加载过多的 DOM 元素

  2. 多次处理一组 DOM 元素,尤其是在您有多个观察者的情况下。

如何解决这个问题:使用 Google 调试分析工具(尤其是堆快照)来跟踪您的 DOM 元素。实际上真的很棒。

很可能你加载了太多不必要的 DOM 元素。尝试通过在范围对象上使用一些标志来延迟加载它们。

例如,我们需要显示一个项目树供用户选择,并且我们预先加载了所有这些项目,总共有几十万个。这削弱了 IE 并减慢了 Chrome。我所做的是仅加载顶级类别,并且仅在扩展类别时才加载子项。寻找一些类似的优化。

这类问题不会出现在包含几千条记录的开发数据库中。它们仅出现在生产数据库和发布日期,因此请花点时间查看文档结构并找出风险点。

您还可以使用 Chrome 调试器的 AnugularJS 选项卡(性能部分)。它是一个很棒的工具,可以在 DOM 元素中显示观察者。看看吧。

【讨论】:

    猜你喜欢
    • 2013-06-06
    • 2013-01-06
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多