简体   繁体   English

调试Angular的摘要周期:如何找到无限循环的原因?

[英]Debugging Angular's digest cycle: How to find the cause of an infinite loop?

I currently am working on some code with lazy-loaded content + controllers. 我目前正在处理一些带有延迟加载内容+控制器的代码。 My code basically works like this fiddle . 我的代码基本上就像这个小提琴一样 However, for some reason, my version does not work, and instead I get an infinite digest cycle whenever angular tries to update it's view. 但是,出于某种原因,我的版本不起作用,而只要角度尝试更新它的视图,我就会获得无限的摘要周期

The issue disappears when I remove ng-include from this simple repeat statement: 当我从这个简单的重复语句中删除ng-include时,问题就消失了:

<div class="container" ng-repeat="pageName in pageNames">
  <div ng-include="pageName"></div>
</div>

Weirdest part: The exact same error occurs even if pageNames is never assigned to the scope. 最奇怪的部分:即使从未将pageNames分配给范围,也会发生exact same error Both scopes (the scope of outer and inner controller - I have each one) can be completely empty (I checked with Batarang - I only have two empty scopes), and I still get the error. 两个范围(外部和内部控制器的范围 - 我每个都有)可以完全为空(我用Batarang检查 - 我只有两个空的范围),我仍然得到错误。

My code is a bit too involved, with too many other dependencies, so posting it here makes no sense. 我的代码有点太复杂,有太多其他依赖项,所以在这里发布是没有意义的。 It's purest version is the fiddle above. 它最纯粹的版本是上面的小提琴。 I cannot find a difference in the logic between the two. 我无法找到两者之间的逻辑差异。 When I inspect my scopes with Batarang, I don't see anything suspicious either: 当我用Batarang检查我的望远镜时,我也没有看到任何可疑的东西:

  • I am not using functions in my scopes 我没有在我的范围中使用函数
  • I did not make use of $watch 我没有使用$watch
  • I did not make use of ng-model 我没有使用ng-model

I conclude that I am not explicitly changing anything, so it must be something under the hood of angular. 我的结论是,我没有明确地改变任何东西,所以它必须是有角度的东西。

Can I somehow get Angular or Batarang to tell me which scope variables have changed after a digest iteration, so I can identify the culprit causing the infinite loop? 我可以以某种方式让Angular或Batarang告诉我在摘要迭代后哪些范围变量已经改变,所以我可以识别导致无限循环的罪魁祸首?

UPDATE: 更新:

I finally figured out that history.pushState messes everything up. 我终于想通了history.pushState把一切history.pushState一团糟。 I am now looking into alternatives, such as the $location service. 我现在正在研究替代方案,例如$location服务。 Nevertheless, I would still like to know how to debug this kind of issue in general. 不过,我仍然想知道如何调试这类问题。 Any hints? 任何提示?

There's no direct way to get a list of scope variables that changed in each digest, but it's really simple to modify Angular's source to do that (temporarily) if you're in an emergency-debugging situation. 没有直接的方法可以获得每个摘要中更改的范围变量列表,但是如果您处于紧急调试状态,则可以非常简单地修改Angular的源(临时)。 The $digest code is here: $ digest代码在这里:

angular.js > src > ng > rootScope.js angular.js > src> ng> rootScope.js

If you look at this method you'll see references to a watchLog array. 如果你看一下这个方法,你会看到对watchLog数组的引用。 AngularJS uses this to report useful error messages when it detects looping like you're getting. AngularJS使用它来报告有用的错误消息,当它检测到您正在获取循环时。 You could easily add a few console.log items here, or maintain your own array that you could log later or inspect with your debugger. 您可以在此处轻松添加一些console.log项,或者维护您自己可以稍后记录的数组或使用调试器进行检查。 You can also set breakpoints here to see what is going on. 您还可以在此处设置断点以查看正在发生的情况。

It's not clear to me why history.pushState() would have anything to do with this because your original question doesn't talk about the use of $location, history, or related functions. 我不清楚为什么history.pushState()与此有关,因为你的原始问题没有讨论$ location,history或相关函数的使用。 However, note that it is a VERY common problem with ngInclude to create infinite loops when paths aren't what you expect. 但是,请注意,当路径不是您期望的时,ngInclude创建无限循环是一个非常常见的问题。 A huge number of server-side (eg NodeJS) projects are configured to return the home/index page when a resource isn't found because they assume there's front-end routing going on. 大量服务器端(例如NodeJS)项目被配置为在找不到资源时返回主页/索引页面,因为它们假设正在进行前端路由。 That's actually a huge problem because you end up embedding your home page in your home page, which then embeds another copy, etc. I see this kind of problem posted about once a week here on S/O. 这实际上是一个很大的问题,因为你最终将主页嵌入主页,然后嵌入另一个副本,等等。我看到这种问题大约每周一次在S / O上发布。

A simple test for this is to alter your server to return an empty 404 for any resource not found. 对此的一个简单测试是更改您的服务器以返回任何未找到的资源的空404。 I always recommend this whenever somebody mentions "infinite loop" and any kind of asset loading operation: ui-router, ngRoute, ngInclude, etc. 每当有人提到“无限循环”和任何类型的资产加载操作时,我总是推荐这个:ui-router,ngRoute,ngInclude等。

This is particularly common when using relative URLs in paths. 在路径中使用相对URL时,这种情况尤为常见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM