각도 필터는 작동하지만 "10$digest 반복 도달"의 원인이 됩니다.
다음과 같이 구성된 백엔드 서버에서 데이터를 수신합니다.
{
name : "Mc Feast",
owner : "Mc Donalds"
},
{
name : "Royale with cheese",
owner : "Mc Donalds"
},
{
name : "Whopper",
owner : "Burger King"
}
제 견해로는 목록을 "반전"하고 싶습니다.즉, 각 주인을 나열하고 해당 주인을 위해 모든 햄버거를 나열해야 합니다.할 수 .groupBy
에 넣어 ★★★★★★★★★★★★★와 함께 사용합니다.ng-repeat
★★★★
JS:
app.filter("ownerGrouping", function() {
return function(collection) {
return _.groupBy(collection, function(item) {
return item.owner;
});
}
});
HTML:
<li ng-repeat="(owner, hamburgerList) in hamburgers | ownerGrouping">
{{owner}}:
<ul>
<li ng-repeat="burger in hamburgerList | orderBy : 'name'">{{burger.name}}</li>
</ul>
</li>
이것은 예상대로 동작하지만 "10 $digest referations reached"라는 오류 메시지와 함께 목록이 렌더링되면 엄청난 오류 스택트레이스가 표시됩니다.내 코드가 이 메시지에 포함된 무한 루프를 생성하는 방법을 이해하는 데 어려움이 있습니다.왜 그런지 아는 사람 있나요?
다음은 코드 http://plnkr.co/edit/8kbVuWhOMlMojp0E5Qbs?p=preview의 플렁크에 대한 링크입니다.
은, 「 」가 원인으로 발생합니다._.groupBy
실행할 때마다 새 개체의 컬렉션을 반환합니다.각도ngRepeat
하다는 못하고 있다ngRepeat
신원을 통해 추적합니다새로운 오브젝트는 새로운 아이덴티티로 이어집니다.이로 인해 Angular는 마지막 검사 이후 뭔가가 변경되었다고 생각하게 됩니다. 즉, Angular는 다른 검사(일명 다이제스트)를 실행해야 합니다.다음 다이제스트는 다른 새 개체 집합을 가져오므로 다른 다이제스트가 트리거됩니다.앵글이 포기할 때까지 반복한다.
오류를 제거하는 한 가지 쉬운 방법은 필터가 매번 동일한 개체 집합을 반환하도록 하는 것입니다(물론 변경되지 않는 한). 쓸 수 요._.memoize
필터 기능을 메모로 감싸기만 하면 됩니다.
app.filter("ownerGrouping", function() {
return _.memoize(function(collection, field) {
return _.groupBy(collection, function(item) {
return item.owner;
});
}, function resolver(collection, field) {
return collection.length + field;
})
});
필터에 다른 필드 값을 사용할 계획인 경우 리졸바 함수가 필요합니다.위의 예에서는 배열의 길이가 사용됩니다.수집을 고유한 md5 해시 문자열로 줄이는 것이 좋습니다.
여기 플런커 포크를 보세요.메모는 특정 입력의 결과를 기억하고 입력이 이전과 동일한 경우 동일한 개체를 반환합니다.값이 자주 변경되는 경우_.memoize
는 오래된 결과를 폐기하여 시간 경과에 따른 메모리 누수를 방지합니다.
좀 더 조사해 보니ngRepeat
구문을 합니다.... track by EXPRESSION
에게 Angular를 이 될 수 owner
레스토랑의 정보를 수집했습니다.은 위의이 될 수, 의 Angular)에서는 수 .에서 테스트할 수 없었습니다.track by
★★★★★★★★★★★★★★★★★★★)
좋아, 이제 알 것 같아.먼저 ngRepeat의 소스 코드를 확인합니다.주의 행 199:여기서 반복하는 어레이/개체에 워치를 설정하여 해당 어레이 또는 해당 요소가 변경되면 다이제스트 사이클이 트리거됩니다.
$scope.$watchCollection(rhs, function ngRepeatAction(collection){
에는 '의미'의 요?$watchCollection
rootScope.js의 360행에서 시작합니다.이 함수는 배열 또는 객체 표현식으로 전달됩니다.이 경우 다음과 같습니다.hamburgers | ownerGrouping
. 에서는 이 표현이 . line 365 、 그열 、 음음음음음음음 the the the the the the the the the the the the the the the the the the the the the the 로 $parse
나중에 호출되는 함수인 service는 이 워처가 실행될 때마다 다음과 같습니다.
var objGetter = $parse(obj);
이 새로운 함수는 필터를 평가하여 어레이를 얻을 수 있으며, 몇 줄 아래쪽에 호출됩니다.
newValue = objGetter(self);
★★★★★★★★★★★★★★★★★.newValue
된 후 데이터 .groupBy는 필터링된 데이터입니다.
다음 408행까지 스크롤하여 다음 코드를 확인합니다.
// copy the items to oldValue and look for changes.
for (var i = 0; i < newLength; i++) {
if (oldValue[i] !== newValue[i]) {
changeDetected++;
oldValue[i] = newValue[i];
}
}
value 、 oldValue 、 ( 「 internal Array 」 ) 。newValue, newValue, newValue, newValue, newValue, newValue, newValue, newValue, newValue.따라서 다음 번 실행 시 모든 것이 일치해야 하며 변경은 검출되지 않습니다.모든 것이 정상적으로 동작하고 있을 때는, 이 코드가 2회 실행됩니다.초기 null 상태로부터의 변경을 검출하는 셋업과 검출된 변경으로 인해 새로운 다이제스트사이클이 강제로 실행되기 때문에 셋업에서 한 번 더 실행됩니다. 이 두 번째 실행 . 이 에서는 변화가 감지되지 않습니다. 왜냐하면 이 시점에서(oldValue[i] !== newValue[i])
「i」의 「i」의 「i」의 「i」의 「」의 「의 출력이, 예에 개 을 알 수 있습니다.console.log에 접속합니다.
그러나 실패하는 경우 필터 코드가 실행될 때마다 새로운 요소를 포함하는 새 어레이를 생성합니다.이 새로운 어레이의 엘리먼트는 이전 어레이의 요소와 동일한 가치(완벽한 복사)를 가지지만 실제 요소는 다릅니다.즉, 메모리의 다른 오브젝트 중 같은 속성과 값을 가진 오브젝트를 말합니다.따라서 고객님의 경우oldValue[i] !== newValue[i]
를 들어, 일 것이다. 같같 、 를를 、 ,를 、{x: 1} !== {x: 1}
항상 진실입니다.을 사용법
따라서 중요한 문제는 필터가 어레이를 실행할 때마다 원래 어레이 엘리먼트의 복사본인 새로운 요소로 구성된 새로운 어레이 복사본을 생성하는 것입니다.따라서 ngRepeat에 의한 워처 설정은 기본적으로 무한 재귀 루프에 머무르며 항상 변경을 검출하고 새로운 다이제스트 사이클을 트리거합니다.
다음은 동일한 문제를 재현하는 간단한 코드 버전입니다.http://plnkr.co/edit/KiU4v4V0iXmdOKesgy7t?p=preview
필터가 실행될 때마다 새 어레이 생성을 중지하면 문제가 사라집니다.
AngularJS 1.2의 새로운 기능은 ng-repeat 디렉티브의 "추적 기준" 옵션입니다.이 명령을 사용하면 Angular가 서로 다른 객체 인스턴스가 실제로 동일한 객체로 간주되어야 한다는 것을 인식할 수 있습니다.
ng-repeat="student in students track by student.id"
이렇게 하면 Underscore를 사용하여 헤비웨이트 슬라이스 및 다이싱을 수행하고 필터링만 하는 것이 아니라 새로운 객체를 생성하는 경우 Angular를 사용할 수 있습니다.
메모화 솔루션 덕분에 잘 작동합니다.
단, _.memoize는 처음 전달된 파라미터를 캐시의 기본 키로 사용합니다.특히 첫 번째 파라미터가 항상 같은 참조일 경우 이 방법은 유용하지 않습니다.이 동작은 를 통해 설정할 수 있습니다.resolver
파라미터를 지정합니다.
다음 예에서는 첫 번째 파라미터는 항상 같은 배열이고 두 번째 파라미터는 어떤 필드에서 그룹화할지를 나타내는 문자열입니다.
return _.memoize(function(collection, field) {
return _.groupBy(collection, field);
}, function resolver(collection, field) {
return collection.length + field;
});
말씀드려 만, 해 .ng-init="thing = (array | fn:arg)"
를 사용합니다.thing
안에서ng-repeat
나한텐 효과가 있지만 이건 광범위한 사안이야.
이 에러가 발생하는 이유를 알 수 없지만 논리적으로 필터 함수는 배열의 각 요소에 대해 호출됩니다.
이 경우 작성한 필터 함수는 어레이의 각 요소가 아닌 어레이가 업데이트되었을 때만 호출되어야 하는 함수를 반환합니다.함수에 의해 반환된 결과는 html로 바운딩할 수 있습니다.
저는 http://plnkr.co/edit/KTlTfFyVUhWVCtX6igsn에서 플런커를 분기하여 독자적인 구현을 작성했습니다.
필터는 사용하지 않습니다.은 '이렇게 하다'라고 예요.groupBy
과
$scope.ownerHamburgers=_.groupBy(hamburgers, function(item) {
return item.owner;
});
$scope.addBurger = function() {
hamburgers.push({
name : "Mc Fish",
owner :"Mc Donalds"
});
$scope.ownerHamburgers=_.groupBy(hamburgers, function(item) {
return item.owner;
});
}
중요한 것은 다음과 같은 간단한 필터가 하나 더 있다는 것입니다.
.filter('paragraphs', function () {
return function (text) {
return text.split(/\n\n/g);
}
})
포함:
<p ng-repeat="p in (description | paragraphs)">{{ p }}</p>
이 되었다.$digest
수 기능: 쉽게 고칠 수 있는 기능:
<p ng-repeat="(i, p) in (description | paragraphs) track by i">{{ p }}</p>
하다.ngRepeat
않는다. 리피터를 좋아하지 않는다"foo\n\nfoo"
두 개의 동일한 단락으로 인해 오류가 발생합니다.단락의 내용이 실제로 변경되고 있고, 계속 소화가 되는 것이 중요하다면, 이 해결책은 적절하지 않을 수 있지만, 나의 경우는 문제가 되지 않습니다.
언급URL : https://stackoverflow.com/questions/16507040/angular-filter-works-but-causes-10-digest-iterations-reached
'programing' 카테고리의 다른 글
$httpBackend 조롱 - "예기치 않은 요청, 더 이상 예상되지 않은 요청" 처리 방법 (0) | 2023.04.03 |
---|---|
워드프레스의 클라우드 프런트 SSL 문제.리다이렉트가 너무 많다 (0) | 2023.04.03 |
.Net에서 JSON 역직렬화 속도를 향상시키는 방법(JSON.net 또는 기타) (0) | 2023.03.29 |
getDerivedStateFromError와 componentDidCatch의 차이점은 무엇입니까? (0) | 2023.03.29 |
리액트 라우터 v6의 컴포넌트 외부 탐색 (0) | 2023.03.29 |