调试 AngularJS 在 Internet Explorer 中锁定的问题

4
我遇到了一个IE10的问题,很容易就能复制。在我的应用程序中,在几个页面中跳转后,IE完全锁定(没有“长时间运行脚本”警告,只是完全冻结)。我必须从任务管理器中终止它。我已经禁用了所有附加组件并进行了清除。我正在一台相当大的工作站上运行(Win7,16GB RAM,i7等)。
在Chrome或Firefox中不会冻结。仅在IE10和IE11中出现此问题。
关于我的应用程序
我正在与工业控制系统集成,以显示我的系统的活动状态。我有很多XHR轮询(将移动到WebSocket,但现在,这很容易与我的API集成)。每500ms从端点刷新数据,更新页面上的一堆字段。
当应用程序没有冻结时,导航非常迅速。找不到任何特定条件导致冻结。
在任何给定时间,我的应用程序具有75到400个$watch(使用this answer计算)。

目前正在运行AngularJS v1.3.0-rc.4。在1.2.25上也遇到了类似的锁死问题。

所以我的问题是

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


也许Visual Studio的分析器更好用:http://msdn.microsoft.com/zh-cn/library/dd264908.aspx - Sergiu Paraschiv
如果你每500毫秒轮询一次,那么$interval的设置/初始化是在控制器还是服务/工厂中?(我知道这与调试无关,只是一个想法) - Brocco
@Brocco 这是在控制器中包含的轮询服务。 (我只使用$timeout而不是$interval,以确保在处理响应和启动下一个请求之间保持最少500毫秒的间隔)。 - Mike Griffith
@MikeGriffith 已经明白了,由于每次都会创建一个新的控制器,我建议在控制器销毁时停止轮询。 - Brocco
@Brocco 是的,我已经确保这样做了(将其绑定到$scope $destroy事件以“注销”轮询)。谢谢你的建议。我的网络活动看起来完全合理,直到IE冻结(此时所有XHR活动都停止命中服务器)。 - Mike Griffith
显示剩余2条评论
2个回答

4

痛苦之余,我能够理解。

您可以将关注点分离开来吗?使用不使用XHR的服务模拟测试您的前端(DOM部分带有ng-repeat),看看是否遇到相同的问题。您还可以尝试在不连接到前端的情况下测试XHR服务。(例如,您可以有一个测试视图,只有像<span>{{myDataArray}}</span>这样的东西,以避免ng-repeat问题,用于测试目的。)基本上,尝试将问题一分为二,看看是否仍然可以复制该问题。

我的想法基本上是这样的:如果您模拟服务并且仍然每500ms轮询,并且遇到了问题,则可能存在IE DOM更新的问题。如果您没有遇到问题,但是测试了真实服务并且IE会冻结,则某处存在XHR问题(也许是您的轮询时间?)或者Angular监视系统存在问题。

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

简而言之,“我下一步该尝试什么?” 您将不得不开始智能修剪一些代码,以查看哪些有效,哪些无效。


我一直在尝试这个,看起来DOM是最麻烦的部分。因此,我已经删除了所有的ng-repeats,改为手工操作DOM(使用防抖动技术以避免在Chrome中频繁触摸IE)。所以,还不完美,但感谢您的提示! - Mike Griffith
@MikeGriffith 说句实话,我完全忘了提到这一点 - 当你使用 ng-repeat 时,通常最好使用 track by 语句。理论上,这可以避免很多不必要的 DOM 重绘(尽管在实践中,我不知道在某个阈值之后会有多少收益)。真正的问题是 DOM 和 digest 循环,因为据我所知,ng-repeat 使用了很多监视器(除了插值内容)。 - user677526

1

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

  1. 加载太多DOM元素

  2. 多次处理一组DOM元素,特别是如果您有多个观察者。

如何解决:使用Google调试分析工具(尤其是堆快照)来跟踪您的DOM元素。这真的非常棒。

很可能您正在加载过多不必要的DOM元素。通过在作用域对象上使用一些标志来使用惰性加载。

例如,我们需要为用户显示一个选择项树,我们一开始加载了全部内容,总计有几十万个。这使IE变得不稳定,并降低了Chrome的速度。我的做法是只加载顶级类别,并且仅在展开类别时才加载子类别。寻找像这样的优化方法。

这些问题不会在具有几千条记录的开发数据库中显示出来。它们只会在生产数据库中和启动日期中显示出来,因此请花时间检查您的文档结构并找到风险点。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接