AngularDart自定义过滤器调用()方法需要是幂等的吗?

时间:2014-01-24 01:53:26

标签: filter dart semantics angular-dart idempotent

Angular Dart教程的主要运行示例是食谱书应用Chapter 5 on filters and services结束时的练习建议尝试" 创建一个[自定义]过滤器,它将使[食谱中列出的每种成分]的所有数量相乘&#34 ;从而允许" 用户将食谱加倍,三倍或四倍。"例如。 " 1/2杯面粉的成分"将成为" 1杯面粉"加倍的时候。

我编写了这样一个自定义过滤器:它包含Ingredient个列表(包含quantitydescription)并返回新的{{1}列表} s(数量增加),但我收到以下错误:

Ingredient

我的问题是: AngularDart自定义过滤器5 $digest() iterations reached. Aborting! 方法的必需和/或允许行为是什么?例如,显然允许从其输入列表中删除(即过滤)元素,但是它是否还可以添加新元素或替换元素? Dart angular.core NgFilter文档只是说"过滤器是一个带调用方法的类"。我还没有找到更多细节。

this AngularJS post的答案推断,似乎call()的重复调用应该(最终?)产生"相同的结果"。如果是这样,这将是一个合理的约束。

屈服"同样的结果"可能意味着call()需要幂等,但在Dart的情况下,这种幂等性应该相对于call()(对象等价)而不是==(对象身份) ), 恕我直言。我使用以下小例子运行了一些测试来说明问题:

  • main.dart
identical()
  • index.html摘录
    import 'package:angular/angular.dart';

    class A { }

    @NgFilter(name:'myFilter') class MutatingCustomFilter {
      final A _a = new A();
      call(List list) => new List.from(list)..add(_a); // runs ok.
      // call(List list) => new List.from(list)..add(new A()); // gives error
    }

    class MyAppModule extends Module {
      MyAppModule() { type(MutatingCustomFilter); }
    }

    main() => ngBootstrap(module: new MyAppModule());

如果我将 <ul> <li ng-repeat="x in [1,2,3] | myFilter">{{x}}</li> </ul> 的正文更改为

class A

使@override bool operator==(other) => true; @override int get hashCode => 1; 的所有实例都被视为A,然后main.dart(==中的call()的第二个实现仍然会出错(尽管另一个)。

我可以看到如何在不使用自定义过滤器的情况下解决教程练习,但我试图不放弃寻找可按要求工作的过滤器的挑战。我是Angular的新手并且决定加入AngularDart,所以任何帮助解释add(new A())的各种风格的影响,或者找到call()的预期行为的文档,(或让我知道你是否认为这样的自定义过滤器根本无法编写!)将不胜感激。

1 个答案:

答案 0 :(得分:5)

迭代次数太多

当角度检测到模型发生变化时,它会执行反应功能。反应函数可以进一步改变模型。这会使模型处于不一致状态。出于这个原因,我们重新运行更改检测,这可以进一步创建更多更改。因此,我们会继续重新运行更改,直到模型稳定下来。但是在放弃之前我们应该多少次重新检查变化检测?默认情况下是5次。如果模型在5次迭代后没有稳定,我们放弃。这就是你的情况。

更改检测

何时更改了对象?可以使用identical==(等于)。可以为每个人提供良好的论据,但我们选择使用identical因为它快速且一致。使用==(等于)很棘手,它会对变化检测算法产生负面影响。

过滤器和数组

当一个操作数组的过滤器执行它时别无选择,只能创建一个新的数组实例。这打破了相同的,但幸运的是它被送入ng-repeat,它使用自己的算法进行数组内容检测而不是数组检测。虽然阵列在运行之间不必相同,但其内容必须是。否则ng-repeat无法区分插入和更改之间的区别,它需要做适当的动画。

您的代码

您的过滤器的问题是它在摘要循环的每次迭代中创建新实例。这些新实例会阻止模型稳定并因此导致错误。 (有计划解决这个问题,但是在我们到达那里之前几周。)

解决方案

您的解决方案正在尝试创建一个过滤器,该过滤器使用整个阵列,然后尝试为ng-repeat创建一个新阵列。一个不同的(首选)解决方案是按原样保留ng-repeat迭代,而是将过滤器放在创建数量的绑定上并将其应用于那里。

<span>{{recipe.qty | myFilter:multiply}}</span>