[英]Table in AngularJS app with many “select” elements built with ng-repeat takes very long
[英]Garbage collection takes a very long time in Internet Explorer after building a large table with ng-repeat AngularJS
我正在使用AngularJS(1.2.26)的ng-repeat指令构建一个大表(3,000多个行)。 数据是一个非常简单的时间和温度数组[[time, temperature], [time, temperature], ...]
的数组。
这是数据在表中的显示方式(使用Slim templating ):
table.table.table-bordered
thead
tr
th.time.first-child= t('Time')
th.temperature.sensor
tbody
tr[bindonce ng-repeat="item in readings"]
td.datetime
span.date bo-text="formatDate(item.time)"
span.time bo-html="formatTime(item.time)"
td bo-text="item.reading.temperature | number: 2"
如您所见,我们正在使用一次绑定库来减少角度观察者的数量。 这是一份报告,因此我们不需要维护数据绑定。
在Chrome或Firefox上,加载数据并呈现报告大约需要4秒钟,而在Internet Explorer(11)上大约需要8秒钟。 但是,在Internet Explorer上构建表之后,浏览器将最多花费两分钟执行垃圾回收(根据UI响应选项卡)。
我需要更多的“声誉”来发布图片,所以我将尽力描述正在发生的事情。
整个表呈现过程是xhr.onreadystatechange
事件侦听器的结果(此后已从1.3中的angular中删除)。 每行和跨度都使用jQuery的appendChild()
-> insertBefore()
函数或浏览器的innerHTML
函数添加到表中。 这些事件发生了数千次,占了我之前提到的〜8秒。 一旦完成这些操作,将立即进行几行垃圾收集,总共需要60秒钟以上的时间。
在没有输出图片的情况下,这是最后一个appendChild()
之后开始执行的时间的列表,然后是总执行时间(窗口中条的长度)。
然后,在其余的过程进行之前,还有大约10 s的间隔。
我不明白这里发生了什么,因为每个垃圾收集都很短,但是它们之间的间隔很长。 我对浏览器中的垃圾收集了解不多,因此妨碍了我的理解。 Chrome或Firefox中不会发生这种情况。
我遵循了有关分析内存分析的各种指南。 我不相信内存泄漏。 同样,由于声誉原因,我无法添加更多链接,但是我跟随的是Chrome浏览器,标题为“ JavaScript Memory Profiling”,而IE浏览器的标题为“ Improving UI Responsiveness”。
还有一点我不确定是否相关,但是如果有必要,我会在这里提及。 当您在此延迟期间运行性能分析会话时,IE表示延迟是在AngularJS $$RAFProvider
的requestAnimationFrame https://github.com/angular/angular.js/blob/master/src/ng/raf.js#L15
函数期间$$RAFProvider
。 这可能与AngularJS为通过ng-repeat添加的每一行触发一个“ enter”事件有关。 到目前为止,我一直在尝试禁用该动画事件而没有运气。
任何建议或故障排除技巧将不胜感激。 具体来说,如果我可以在垃圾回收上添加一个断点以查看发生了什么,那将是很好的,但是我认为我不能做到这一点。
经过大量调查,我认为我找出了问题所在,或者至少是一个潜在问题。
我绘制的表有两列-时间和温度。 时间列具有两个<span>
元素。 因此,对于每一行,Angular都为ng-repeat
每个元素标记“输入”动画的元素。 作为Angular动画过程的一部分,Angular通过$ RAFProvider从浏览器请求动画帧。 当我在Internet Explorer中分析该过程并查看调用堆栈时,这就是巨大的延迟所在。 我最初以为这不是问题,但是经过大量的故障排除后,我开始认为Internet Explorer的requestAnimationFrame方法无法像Chrome或Firefox一样快地处理约9000个调用。
为了解决这个问题,我选择实现ngInfiniteScroll,并且效果很好。 如果用户确实想要完整的报告,我们将通过不同的代码路径生成完整的3,000行报告。
对于ng-repeat,angular将为双向绑定的每个项目重复创建一个作用域。 但是在您的代码中,没有必要,您只需要显示数据即可。
如果您使用的是angularjs 1.3.x以上版本,则可以使用binging-once功能,那么将不会创建这些作用域。
我不熟悉该模板。 但是您在TR中使用“ bindonce”,如果在angularjs中使用“ bindonce”,我认为您应该使用1.3.x版本。
另一个问题是:
span.date bo-text="formatDate(item.time)"
您使用函数的数据格式。 并且作为上述问题,您应该使用“一次绑定”。 如果使用js,则为:
<span>{{::formatDate(item.time)}}</span>
添加“ ::”一次绑定。
如果您一次不添加绑定,则在表格上滚动时,同一项目的格式函数将被调用多次。 因此,对于格式,您应该使用日期过滤器,例如:
<span>{{item.time | date: 'yyyy/MM/DD'}}</span>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.