$ digest () 반복 10 회에 도달했습니다. 중단!
"최근 5 번의 반복에서 발생한 Watchers :"등의 지원 텍스트가 많이 있지만이 텍스트의 대부분은 다양한 기능의 Javascript 코드입니다. 이 문제를 진단하기위한 경험 규칙이 있습니까? 항상 완화 할 수있는 문제입니까? 아니면이 문제를 경고로 취급해야 할 정도로 복잡한 응용 프로그램이 있습니까?
답변:
Ven가 말했듯이, 당신은 각 $digest
주기 마다 다른 (동일하지 않은) 객체를 반환 하거나 데이터를 너무 많이 변경하고 있습니다.
앱의 어느 부분이이 동작을 일으키는 지 알아내는 가장 빠른 솔루션은 다음과 같습니다.
$scope
각 $digest
주기 에서 개체를 변경 하거나 동일하지 않은 개체를 반환 합니다.$digest
1 단계 후에도 반복 경고 가 계속 발생하면 의심스러운 일을하고있을 것입니다. 상위 템플릿 / 범위 / 컨트롤러에 대해 동일한 단계를 반복합니다.또한 사용자 정의 필터의 입력을 변경하지 않는지 확인하고 싶습니다.
JavaScript에는 일반적으로 예상하는 것처럼 작동하지 않는 특정 유형의 객체가 있습니다.
new Boolean(true) === new Boolean(true) // false
new Date(0) == new Date(0) // false
new String('a') == new String('a') // false
new Number(1) == new Number(1) // false
[] == [] // false
new Array == new Array // false
({})==({}) // false
map()
와 groupBy()
메이크업의 SHURE보다 당신 있다는 $watch
말이지으로 더러운 검사 수행 objectEquality
$watch('myFunctionDoingGropby',callback,true)
참조 docs.angularjs.org/api/ng.$rootScope.Scope#$watch
$scope
할당 된 변수로 바꿀 수 _.map
있었지만 일반적으로 객체 평등에 의한 더티 검사에 어떤 영향을 미칠까요? 작동하지 않는 수동 생성 $watch
이 아니지만 ngRepeat
?
일반적으로 매번 다른 개체를 반환 할 때 발생합니다.
예를 들어 다음에서 사용하는 경우 ng-repeat
:
$scope.getObj = function () {
return [{a: 1}, {b: 2}];
};
Angular가 "안정성"을 가지려고하고 동일한 결과를 2 번 반환 할 때까지 (와 비교하여 ===
) 함수를 실행하기 때문에이 오류 메시지가 표시됩니다.이 경우 함수가 항상 a를 반환하기 때문에 true를 반환하지 않습니다. 새 개체.
console.log({} === {}); // false. Those are two different objects!
이 경우 개체를 범위에 직접 저장하여 수정할 수 있습니다.
$scope.objData = [{a: 1}, {b: 2}];
$scope.getObj = function () {
return $scope.objData;
};
이렇게하면 항상 동일한 객체를 반환합니다!
console.log($scope.objData === $scope.objData); // true (a bit obvious...)
(복잡한 응용 프로그램에서도 이러한 문제가 발생해서는 안됩니다.)
업데이트 : Angular 는 웹 사이트에 좀 더 자세한 설명을 추가했습니다 .
이 솔루션을 여기에 넣고 싶었습니다. 다른 사람들에게 도움이되기를 바랍니다. 호출 될 때마다 새 개체를 만드는 생성 된 속성을 반복했기 때문에이 반복 문제가 발생했습니다.
처음 요청했을 때 생성 된 개체를 캐싱 한 다음 항상 캐시가있는 경우 반환하여 수정했습니다. dirty () 메서드도 추가되어 필요에 따라 캐시 된 결과를 파괴합니다.
나는 다음과 같은 것을 가지고 있었다.
function MyObj() {
var myObj = this;
Object.defineProperty(myObj, "computedProperty" {
get: function () {
var retObj = {};
return retObj;
}
});
}
그리고 구현 된 솔루션은 다음과 같습니다.
function MyObj() {
var myObj = this,
_cached;
Object.defineProperty(myObj, "computedProperty" {
get: function () {
if ( !_cached ) {
_cached = {};
}
return _cached;
}
});
myObj.dirty = function () {
_cached = null;
}
}
또한 무한 루프가 아닐 가능성도 있습니다. 10 번의 반복은 어느 정도 확실하게 결론을 내리기에 충분하지 않습니다. 따라서 야생 거위 추적을 시작하기 전에 먼저 그 가능성을 배제하는 것이 좋습니다.
이를 수행하는 가장 쉬운 방법은 최대 다이제스트 루프 수를 훨씬 더 큰 수로 늘리는 것입니다. 이는 module.config
메서드를 사용하여 $rootScopeProvider.digestTtl(limit)
메서드 에서 수행 할 수 있습니다 . 경우 infdig
오류가 더 이상 표시되지 않습니다 당신은 단순히 어떤 충분히 복잡한 업데이트 논리를 가지고있다.
당신이 재귀 시계에 의존하는 데이터 또는 뷰를 구축 할 경우에 당신은 사용 (예 : 시작하는 새로운 소화 루프에 의존하지 않음) 반복적 인 솔루션을 검색 할 수 있습니다 while
, for
또는 Array.forEach
. 때로는 구조가 고도로 중첩되고 재귀 적이 지 않은 경우도 있습니다. 이러한 경우 제한을 높이는 것 외에는 할 일이 많지 않을 것입니다.
오류를 디버깅하는 또 다른 방법은 다이제스트 데이터를 보는 것입니다. JSON을 예쁘게 인쇄하면 배열 배열을 얻을 수 있습니다. 각 최상위 항목은 반복을 나타내며 각 반복은 감시 항목 목록으로 구성됩니다.
예를 들어 $watch
자체적으로 수정 된 속성이있는 경우 값이 무한대로 변경되는 것을 쉽게 알 수 있습니다.
$scope.vm.value1 = true;
$scope.$watch("vm.value1", function(newValue)
{
$scope.vm.value1 = !newValue;
});
[
[
{
"msg":"vm.value1",
"newVal":true,
"oldVal":false
}
],
[
{
"msg":"vm.value1",
"newVal":false,
"oldVal":true
}
],
[
{
"msg":"vm.value1",
"newVal":true,
"oldVal":false
}
],
[
{
"msg":"vm.value1",
"newVal":false,
"oldVal":true
}
],
[
{
"msg":"vm.value1",
"newVal":true,
"oldVal":false
}
]
]
물론 더 큰 프로젝트에서 이것은 간단하지 않을 수 있습니다. 특히 시계가 보간 인 경우 msg
필드에 값이있는 경우가 많기 때문 입니다."fn: regularInterceptedExpression"
{{ }}
그 외에도 문제의 원인을 찾기 위해 HTML을 자르는 것과 같은 이미 언급 한 방법이 도움이됩니다.
나는 똑같은 문제가 있었다-나는 매번 새로운 날짜를 만들고 있었다. 따라서 날짜를 다루는 모든 사람을 위해 다음과 같이 모든 호출을 변환했습니다.
var date = new Date(); // typeof returns object
에:
var date = new Date().getTime(); // typeof returns number
날짜 개체 대신 숫자를 초기화하면 문제가 해결되었습니다.
에서 알려진 버그입니다 ui-router
. 이로 인해 도움이되었습니다 : https://github.com/angular-ui/ui-router/issues/600
또한 내 프로젝트에있는 사용자 지정 지시문의 templateUrl에 오타가있을 때이 오류 메시지를 받았다고 언급하고 싶습니다. 오타로 인해 템플릿을로드 할 수 없습니다.
/* @ngInject */
function topNav() {
var directive = {
bindToController: true,
controller: TopNavController,
controllerAs: 'vm',
restrict: 'EA',
scope: {
'navline': '=',
'sign': '='
},
templateUrl: 'app/shared/layout/top-navTHIS-IS-A-TYPO.html'
};
웹 브라우저 개발 도구의 네트워크 탭에서 404 오류가있는 리소스가 있는지 확인합니다.
오류 메시지가 매우 비밀스럽고 실제 문제와 관련이없는 것처럼 보이기 때문에 간과하기 쉽습니다.
이 일을했기 때문에이 문제가 발생했습니다.
var variableExpense = this.lodash.find(product.variableExpenseList, (ve) => {
return ve.rawMaterial.id = rawMaterial.id;
});
대신에 : (notice = vs ===), 내 단위 테스트가 깨지기 시작했고 내 어리 석음을 발견했습니다.
var variableExpense = this.lodash.find(product.variableExpenseList, (ve) => {
return ve.rawMaterial.id === rawMaterial.id;
});
동적 툴팁이 필요한이 문제가 발생했습니다. angular가 매번 새 값으로 다시 계산하도록했습니다 (동일한 경우에도). 다음과 같이 계산 된 값을 캐시하는 함수를 만들었습니다.
$ctrl.myObj = {
Title: 'my title',
A: 'first part of dynamic toolip',
B: 'second part of dynamic tooltip',
C: 'some other value',
getTooltip: function () {
// cache the tooltip
var obj = this;
var tooltip = '<strong>A: </strong>' + obj.A + '<br><strong>B: </strong>' + obj.B;
var $tooltip = {
raw: tooltip,
trusted: $sce.trustAsHtml(tooltip)
};
if (!obj.$tooltip) obj.$tooltip = $tooltip;
else if (obj.$tooltip.raw !== tooltip) obj.$tooltip = $tooltip;
return obj.$tooltip;
}
};
그런 다음 html에서 다음과 같이 액세스했습니다.
<input type="text" ng-model="$ctrl.myObj.C" uib-tooltip-html="$ctrl.myObj.getTooltip().trusted">
이것이 내가 접근하여 해결책을 찾은 방법입니다. 텍스트를 확인한 결과 다음과 같이 표시되었습니다.
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
최근 5 회 반복에서 발동 된 감시자 : [[{ "msg": "statement === statment && functionCall ()", "newVal": [{ "id": 7287, "참조 ...
그래서 당신이 볼 수 있다면
메시지
그것이 오류를 생성하는 문구입니다. 이 메시지에서 호출 된 함수를 확인한 후 문제가있는 항목을 확인하기 위해 모두에서 (false)를 반환했습니다. 그들 중 하나는 수익을 계속 변경하는 함수를 호출하고 있었는데 이것이 문제였습니다.