AngularJS 过滤器中的无限摘要循环
Infinite Digest Loop in AngularJS filter
我已经为 AngularJS 编写了这个自定义过滤器,但是当它运行时,我遇到了无限摘要循环错误。为什么会发生这种情况,我该如何纠正?
angular.module("app", []).
filter('department', function(filterFilter) {
return function(items, args) {
var productMatches;
var output = [];
var count = 0;
if (args.selectedDepartment.Id !== undefined && args.option) {
for (let i = 0; i < items.length; i++) {
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
}
}
return output;
};
}).
这是相关的 HTML:
<tr class='destination' ng-repeat-start='pickupAccount in pickupAccounts | department : {"selectedDepartment": selectedDepartment, "option": displayExclusive }'>
<!-- td here -->
</tr>
displayExclusive
是布尔值。
当您以与原始数组不匹配的方式操作返回的数组时,就会发生这种情况。参见示例:
.filter("department", function() {
return function(items, args) {
var output = [];
for (var i = 0; i < items.length; i++) {
output[i] = {};
output[i] = items[i]; // if you don't do this, the next filter will fail
output[i].product = items[i];
}
return output;
}
}
您可以在以下简化的 jsfiddle 中看到它的发生:https://jsfiddle.net/u873kevp/1/
如果返回的数组确实与输入数组具有相同的 'structure',则会导致这些错误。
只需将原始项目分配给退回的项目,它就可以解决您的问题:
if (productMatches.length !== 0) {
output[count] = items[i]; // do this
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
I have written this custom filter for AngularJS, but when it runs, I get the infinite digest loop error.
请记住,过滤器应该 return 具有相同对象结构的数组。当我们激活过滤器时,它会触发摘要循环,将 运行 再次覆盖我们的过滤器。如果输出列表中发生了某些变化 - 触发新的摘要循环等等。尝试 10 次后,它会抛出 Infinite Digest Loop
异常
测试
这个空过滤器可以工作 (100%)。实际上我们在这里除了 return 过滤器接收的同一个对象外什么都不做。
filter('department', function(filterFilter) {
return function(items, args) {
var output = items;
return output;
};
})
现在的主要思想是:编写一些条件以从输入列表 a.e 中推送到 output
个对象。 items
基于某些 if
语句,a.e.
var output = [];
if (args.selectedDepartment.Id !== undefined && args.option) {
angular.forEach(items, function(item) {
if(<SOME CONDITION>) {
output.push(item);
}
});
}
这样也行。
我们的案例:
我们有这样的逻辑:
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
这里我们完全修改了存储在output
中的对象。
所以下一个摘要周期我们的 items
将一次又一次地改变。
结论
filter
的主要目的是过滤列表,而不是修改列表对象内容。
上面提到的你写的逻辑与数据操作有关,而不是过滤器。 department
过滤器 return 具有相同长度的项目。
为了实现你的目标,你可以使用lodash map or underscorejs map作为例子。
output[count] = {};
上一行是主要问题。你创建一个新实例,ng-repeat
会检测到模型无限期地不断变化。 (虽然你认为从 UI 的角度来看没有任何改变)
为了避免这个问题,基本上你需要确保模型中的每个元素都保持 'same',即
firstCallOutput[0] == secondCallOutput[0]
&& firstCallOutput[1] == secondCallOutput[1]
&& firstCallOutput[2] == secondCallOutput[2]
...
只要不更改模型,就应该保持这种相等性,因此ng-repeat
不会'wrongly'认为模型已更改。
请注意两个新实例不相等,即{} != {}
我已经为 AngularJS 编写了这个自定义过滤器,但是当它运行时,我遇到了无限摘要循环错误。为什么会发生这种情况,我该如何纠正?
angular.module("app", []).
filter('department', function(filterFilter) {
return function(items, args) {
var productMatches;
var output = [];
var count = 0;
if (args.selectedDepartment.Id !== undefined && args.option) {
for (let i = 0; i < items.length; i++) {
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
}
}
return output;
};
}).
这是相关的 HTML:
<tr class='destination' ng-repeat-start='pickupAccount in pickupAccounts | department : {"selectedDepartment": selectedDepartment, "option": displayExclusive }'>
<!-- td here -->
</tr>
displayExclusive
是布尔值。
当您以与原始数组不匹配的方式操作返回的数组时,就会发生这种情况。参见示例:
.filter("department", function() {
return function(items, args) {
var output = [];
for (var i = 0; i < items.length; i++) {
output[i] = {};
output[i] = items[i]; // if you don't do this, the next filter will fail
output[i].product = items[i];
}
return output;
}
}
您可以在以下简化的 jsfiddle 中看到它的发生:https://jsfiddle.net/u873kevp/1/
如果返回的数组确实与输入数组具有相同的 'structure',则会导致这些错误。
只需将原始项目分配给退回的项目,它就可以解决您的问题:
if (productMatches.length !== 0) {
output[count] = items[i]; // do this
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
I have written this custom filter for AngularJS, but when it runs, I get the infinite digest loop error.
请记住,过滤器应该 return 具有相同对象结构的数组。当我们激活过滤器时,它会触发摘要循环,将 运行 再次覆盖我们的过滤器。如果输出列表中发生了某些变化 - 触发新的摘要循环等等。尝试 10 次后,它会抛出 Infinite Digest Loop
异常
测试
这个空过滤器可以工作 (100%)。实际上我们在这里除了 return 过滤器接收的同一个对象外什么都不做。
filter('department', function(filterFilter) {
return function(items, args) {
var output = items;
return output;
};
})
现在的主要思想是:编写一些条件以从输入列表 a.e 中推送到 output
个对象。 items
基于某些 if
语句,a.e.
var output = [];
if (args.selectedDepartment.Id !== undefined && args.option) {
angular.forEach(items, function(item) {
if(<SOME CONDITION>) {
output.push(item);
}
});
}
这样也行。
我们的案例:
我们有这样的逻辑:
productMatches = items[i].products.filter(function(el) {
return el.Order__r.Department__r.Id === args.selectedDepartment.Id;
});
if (productMatches.length !== 0) {
output[count] = {};
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}
这里我们完全修改了存储在output
中的对象。
所以下一个摘要周期我们的 items
将一次又一次地改变。
结论
filter
的主要目的是过滤列表,而不是修改列表对象内容。
上面提到的你写的逻辑与数据操作有关,而不是过滤器。 department
过滤器 return 具有相同长度的项目。
为了实现你的目标,你可以使用lodash map or underscorejs map作为例子。
output[count] = {};
上一行是主要问题。你创建一个新实例,ng-repeat
会检测到模型无限期地不断变化。 (虽然你认为从 UI 的角度来看没有任何改变)
为了避免这个问题,基本上你需要确保模型中的每个元素都保持 'same',即
firstCallOutput[0] == secondCallOutput[0]
&& firstCallOutput[1] == secondCallOutput[1]
&& firstCallOutput[2] == secondCallOutput[2]
...
只要不更改模型,就应该保持这种相等性,因此ng-repeat
不会'wrongly'认为模型已更改。
请注意两个新实例不相等,即{} != {}