example - ciclo digest angularjs
Infinite Digest Loop en el filtro AngularJS (3)
He escrito este filtro personalizado para AngularJS, pero cuando se ejecuta, obtengo el error de bucle de compilación infinito. ¿Por qué ocurre esto y cómo puedo corregirlo?
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;
};
}).
Este es el HTML relevante:
<tr class=''destination'' ng-repeat-start=''pickupAccount in pickupAccounts | department : {"selectedDepartment": selectedDepartment, "option": displayExclusive }''>
<!-- td here -->
</tr>
displayExclusive
es booleano.
He escrito este filtro personalizado para AngularJS, pero cuando se ejecuta, obtengo el error de bucle de compilación infinito.
Tenga en cuenta que el filtro debe devolver una matriz de la misma estructura de objeto. Cuando activamos el filtro, se activa el ciclo de resumen que se ejecutará sobre nuestro filtro de nuevo. Si algo cambió en la lista de salida, se inicia un nuevo ciclo de resumen y así sucesivamente. después de 10 intentos, nos lanzará la excepción Infinite Digest Loop
Pruebas
Este filtro vacío funcionará (100%). En realidad, aquí no hacemos nada más que devolver el mismo objeto que recibe el filtro.
filter(''department'', function(filterFilter) {
return function(items, args) {
var output = items;
return output;
};
})
Ahora la idea principal es: escribir alguna condición para empujar a output
objetos de output
de la lista de entrada ae los items
basados en alguna sentencia if
, ae
var output = [];
if (args.selectedDepartment.Id !== undefined && args.option) {
angular.forEach(items, function(item) {
if(<SOME CONDITION>) {
output.push(item);
}
});
}
De esta manera funcionará también.
nuestro caso:
tenemos esta lógica
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++;
}
Aquí modificamos completamente el objeto que se ha almacenado en la output
. Así que el próximo ciclo de digestión de nuestros items
cambiará una y otra vez.
Conclusión
El propósito principal del filter
es filtrar la lista y no modificar el contenido del objeto de la lista.
La lógica mencionada anteriormente que usted escribió está relacionada con la manipulación de datos y no con el filtro. El filtro de department
devuelve la misma longitud de elementos.
Para lograr su objetivo, puede usar el mapa lodash o el mapa de guiones bajos, por ejemplo.
output[count] = {};
Por encima de la línea es el principal problema. Crea una nueva instancia, y ng-repeat
detectará que el modelo cambia constantemente de forma indefinida. (mientras que piensas que nada ha cambiado desde la perspectiva de la interfaz de usuario)
Para evitar el problema, básicamente debe asegurarse de que cada elemento del modelo siga siendo el mismo, es decir,
firstCallOutput[0] == secondCallOutput[0]
&& firstCallOutput[1] == secondCallOutput[1]
&& firstCallOutput[2] == secondCallOutput[2]
...
Esta igualdad debe mantenerse siempre que no cambie el modelo, por lo tanto, ng-repeat
no pensará "erróneamente" que el modelo ha sido cambiado.
Tenga en cuenta que dos instancias nuevas no son iguales, es decir, {} != {}
Esto sucede cuando manipula la matriz devuelta de una manera que no coincide con la matriz original. Ver por ejemplo:
.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;
}
}
Puede verlo en el siguiente jsfiddle simplificado: https://jsfiddle.net/u873kevp/1/
Si la matriz devuelta tiene la misma ''estructura'' que la matriz de entrada, causará estos errores.
Debería funcionar en su caso simplemente asignando el artículo original al artículo devuelto:
if (productMatches.length !== 0) {
output[count] = items[i]; // do this
output[count].products = productMatches;
output[count].firstProduct = items[i].firstProduct;
count++;
}