当前位置: 首页 > 面试题库 >

角度过滤器有效,但会导致“达到10次$ digest迭代”

淳于升
2023-03-14
问题内容

我从后端服务器接收数据,其结构如下:

{
  name : "Mc Feast",
  owner :  "Mc Donalds"
}, 
{
  name : "Royale with cheese",
  owner :  "Mc Donalds"
}, 
{
  name : "Whopper",
  owner :  "Burger King"
}

以我的观点,我想“反转”列表。即,我想列出每个所有者,并为该所有者列出所有汉堡包。我可以通过groupBy在过滤器中使用underscorejs函数来实现此目的,然后将其与ng- repeat指令一起使用:

JS:

app.filter("ownerGrouping", function() {
  return function(collection) {
    return _.groupBy(collection, function(item) {
      return item.owner;
    });
  }
 });

HTML:

<li ng-repeat="(owner, hamburgerList) in hamburgers | ownerGrouping">
  {{owner}}:  
  <ul>
    <li ng-repeat="burger in hamburgerList | orderBy : 'name'">{{burger.name}}</li>
  </ul>
</li>

这可以按预期工作,但是当使用错误消息“达到10个$
digest迭代次数”来呈现列表时,我得到了一个巨大的错误堆栈跟踪。我很难看到我的代码如何创建此消息暗示的无限循环。有谁知道为什么吗?

这是一个代码如下的链接:http
://plnkr.co/edit/8kbVuWhOMlMojp0E5Qbs?
p=
preview


问题答案:

发生这种情况是因为每次运行时都会_.groupBy返回 对象的集合。Angular
ngRepeat并没有意识到那些对象是相等的,因为ngRepeat它们通过 identity来
跟踪它们。新对象导致新身份。这使Angular认为自上一次检查以来已发生了某些变化,这意味着Angular应该运行另一个检查(即摘要)。下一个摘要将最终获得另一组新对象,因此将触发另一个摘要。重复直到Angular放弃。

消除错误的一种简单方法是确保您的过滤器每次都返回相同的对象集合(当然,除非它已更改)。您可以使用下划线很容易地做到这一点_.memoize。只需将过滤器功能包装在备忘录中即可:

app.filter("ownerGrouping", function() {
  return _.memoize(function(collection, field) {
    return _.groupBy(collection, function(item) {
      return item.owner;
    });
  }, function resolver(collection, field) {
    return collection.length + field;
  })
});

如果您计划对过滤器使用不同的字段值,则需要解析器功能。在上面的示例中,使用了数组的长度。最好将集合减少为唯一的md5哈希字符串。

在这里看到油门叉。Memoize将记住特定输入的结果,如果输入与以前相同,则返回相同的对象。但是,如果值经常更改,则应检查是否_.memoize丢弃旧结果,以免随着时间的推移而发生内存泄漏。

进一步研究,我看到它ngRepeat 支持扩展的语法... track by EXPRESSION,通过允许您告诉Angular查看owner餐厅的名称而不是对象的身份,这可能会有所帮助。这将是上述记忆技巧的替代方法,尽管我无法在插件中测试它(可能是以前track by实施的Angular的旧版本?)。



 类似资料:
  • 问题内容: 我正在尝试使用Angular创建Metro Tile类型的网格,以实现这一目标,我希望每个瓷砖都具有不同的颜色。因此,我的行动计划是创建一个函数,该函数将在循环内随机选择一种颜色(使用)。这是我到目前为止所拥有的… 如您所见,我正在使用名为RandomColourClass的函数设置类名称,这是JS位 这一切工作正常,并且图块具有不同的颜色,但我一直收到以下错误 错误:达到10个$ d

  • 问题内容: 我是Angular的新手,并且遇到了与IE相关的问题。 这是我得到的IE错误。 在IE 8和IE 9之外的任何其他浏览器中都不会发生这种情况。 我有一只手表在看一个包含位置过滤器的内容过滤对象。 我对此的疑问是,为什么它不会在除IE之外的任何其他浏览器上发生,并且我应该怎么做才能消除它。提前致谢。 问题答案: 我有相同的问题,看起来却一样。Chrome \ FF工作正常,但IE失败。我

  • 问题内容: 达到10个$ digest()迭代。流产! 有很多支持文本,例如“在最近5个迭代中触发了Watchers:”等,但是其中很多文本是来自各种功能的Javascript代码。有诊断此问题的经验法则吗?是可以始终缓解的问题,还是应用程序足够复杂,因此应将其视为警告? 问题答案: 正如Ven所说,您或者在每个循环中返回不同(不相同)的对象,或者您将数据更改了太多次。 确定您的应用程序的哪个部分

  • 问题内容: 我有以下代码重复并显示用户名及其分数: 以及相应的角度控制器。 当我运行上面的代码时,我得到 错误:10 $ digest()迭代达到。 流产!我的控制台错误。 我已经为它创建了jsfiddle。 排序谓词仅在ng-repeat内部初始化,并且限制也应用于对象数。所以我觉得将sortby和limitTo监视者放在一起是错误的原因。 如果$ scope.reverse为false(分数的

  • 问题内容: 我想在 angularjs 1.2中 使用unsafe-html 。没有html的过滤器可以工作,而html则不能。我做的事: 我在我的html头中添加了angular-sanitize: 我的角度模块: 我的HTML: 编辑:更新为 问题答案: 已在Angular 1.2中删除。由于您正确地清理了输入内容,因此应该使用。 示例:http://plnkr.co/edit/0bHeXra

  • 我有完全合法的数据来源: 我将其显示在这样的表中: 现在假设我想过滤我的数组。如果我有固定的行数,我可以在< code>tr元素上使用< code>*ngIf来选择显示/不显示一个项目,但是Angular不允许在一个元素上有两个结构指令。 我知道我可以使用< code>Array.filter简单地过滤源数组,但是这样会产生一个副本,如果我的数组大得多,这可能会成为一个问题。 我想将该行嵌套在某个