[angularjs] Angular “10 $ digest () 반복에 도달했습니다”오류 문제를 해결하는 방법

$ digest () 반복 10 회에 도달했습니다. 중단!

“최근 5 번의 반복에서 발생한 Watchers :”등의 지원 텍스트가 많이 있지만이 텍스트의 대부분은 다양한 기능의 Javascript 코드입니다. 이 문제를 진단하기위한 경험 규칙이 있습니까? 항상 완화 할 수있는 문제입니까? 아니면이 문제를 경고로 취급해야 할 정도로 복잡한 응용 프로그램이 있습니까?



답변

Ven가 말했듯이, 당신은 각 $digest주기 마다 다른 (동일하지 않은) 객체를 반환 하거나 데이터를 너무 많이 변경하고 있습니다.

앱의 어느 부분이이 동작을 일으키는 지 알아내는 가장 빠른 솔루션은 다음과 같습니다.

  1. 모든 의심스러운 HTML 제거-기본적으로 템플릿에서 모든 HTML을 제거하고 경고가 없는지 확인합니다.
  2. 경고가없는 경우-제거한 html의 작은 부분을 추가하고 문제가 다시 발생하는지 확인하십시오.
  3. 경고가 표시 될 때까지 2 단계를 반복합니다. 문제의 원인이되는 HTML 부분을 파악할 수 있습니다.
  4. 추가 조사-3 단계의 부품은 $scope$digest주기 에서 개체를 변경 하거나 동일하지 않은 개체를 반환 합니다.
  5. $digest1 단계 후에도 반복 경고 가 계속 발생하면 의심스러운 일을하고있을 것입니다. 상위 템플릿 / 범위 / 컨트롤러에 대해 동일한 단계를 반복합니다.

또한 사용자 정의 필터의 입력을 변경하지 않는지 확인하고 싶습니다.

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


답변

일반적으로 매번 다른 개체를 반환 할 때 발생합니다.

예를 들어 다음에서 사용하는 경우 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

날짜 개체 대신 숫자를 초기화하면 문제가 해결되었습니다.


답변

쉬운 방법은 min 파일이 아닌 angular.js를 사용하는 것입니다. 그것을 열고 줄을 찾으십시오.

if ((dirty || asyncQueue.length) && !(ttl--)) {

아래에 줄 추가 :

console.log("aaaa",watch)

개발 도구 콘솔에서 페이지를 새로 고치면 오류 코드를 찾을 수 있습니다.


답변

에서 알려진 버그입니다 ui-router. 이로 인해 도움이되었습니다 : https://github.com/angular-ui/ui-router/issues/600