[javascript] 거대한 데이터 세트 (angular.js)에서 ngRepeat의 성능을 향상시키는 방법은 무엇입니까?

약 10MB의 필드, 약 2MB의 데이터가있는 수천 행의 거대한 데이터 세트가 있습니다. 브라우저에 표시해야합니다. 가장 간단한 접근 방식 (데이터 가져 오기, 넣기 $scope, ng-repeat=""작업 수행)은 제대로 작동하지만 DOM에 노드 삽입을 시작하면 약 0.5 분 동안 브라우저가 정지됩니다. 이 문제에 어떻게 접근해야합니까?

한 가지 옵션은 $scope점진적으로 행을 추가 ngRepeat하고 한 청크를 DOM에 삽입 하기 를 기다렸다가 다음 행으로 이동하는 것입니다. 그러나 AFAIK ngRepeat는 “반복”이 끝나면 다시보고하지 않으므로 추악합니다.

다른 옵션은 서버의 데이터를 페이지로 분할하여 여러 요청에서 가져 오는 것이지만 훨씬 더 나쁩니다.

과 같은 것을 찾기 위해 Angular 설명서를 살펴 보았지만 ng-repeat="data in dataset" ng-repeat-steps="500"아무것도 찾지 못했습니다. 나는 Angular 방식에 상당히 익숙하지 않으므로 포인트가 완전히 누락되었을 수 있습니다. 이 모범 사례는 무엇입니까?



답변

@ AndreM96에 동의하는 가장 좋은 방법은 제한된 양의 행, 더 빠르고 더 나은 UX 만 표시하는 것입니다. 이는 페이지 매김 또는 무한 스크롤로 수행 할 수 있습니다.

Angular를 사용한 무한 스크롤은 limitTo 필터를 사용 하면 정말 간단 합니다. 초기 제한을 설정해야하며 사용자가 더 많은 데이터를 요청하면 (단순화를 위해 버튼을 사용하고 있음) 제한을 증가시킵니다.

<table>
    <tr ng-repeat="d in data | limitTo:totalDisplayed"><td>{{d}}</td></tr>
</table>
<button class="btn" ng-click="loadMore()">Load more</button>

//the controller
$scope.totalDisplayed = 20;

$scope.loadMore = function () {
  $scope.totalDisplayed += 20;
};

$scope.data = data;

여기에 JsBin이 있습니다.

이 방법은 많은 양의 데이터를 스크롤 할 때 일반적으로 지연되기 때문에 전화에 문제가 될 수 있으므로이 경우 페이지 매김이 더 적합하다고 생각합니다.

이를 위해서는 limitTo 필터와 표시되는 데이터의 시작점을 정의하는 사용자 정의 필터가 필요합니다.

페이지 매김 이있는 JSBin 이 있습니다.


답변

대규모 데이터 세트로 이러한 과제를 극복하기위한 가장 인기 있고 확장 성이 뛰어난 방법은 Ionic의 collectionRepeat 지시문 및 이와 유사한 다른 구현 방식으로 구현됩니다. 이것에 대한 멋진 용어는 ‘오 클루 전 컬링’ 이지만, 요약하면 렌더링 된 DOM 요소의 수를 50, 100, 500과 같은 임의의 (그러나 여전히 높은) 페이지 매김 된 숫자로 제한하지 마십시오 … , 제한 사용자 만 많은 요소를 볼 수에 .

일반적으로 “무한 스크롤”로 알려진 것과 같은 작업을 수행하는 경우 초기 DOM 수를 약간 줄이려고하지만 몇 가지 새로 고침 후에는 모든 새 요소가 맨 아래에 고정되어 있기 때문에 빠르게 증가합니다. 스크롤은 요소 수에 관한 것이기 때문에 스크롤이 크롤링됩니다. 그것에 대해 무한한 것은 없습니다.

반면, collectionRepeat접근 방식은 뷰포트에 맞는만큼의 요소 만 사용한 다음 재활용하는 것 입니다. 한 요소가 시야에서 벗어나면 렌더 트리에서 분리되어 목록의 새 항목에 대한 데이터로 다시 채워진 다음 목록의 다른 쪽 끝에있는 렌더 트리에 다시 연결됩니다. 이것은 사람이 DOM으로 들어오고 나가는 새로운 정보를 얻는 가장 빠른 방법으로, 기존의 생성 / 파괴주기 인 생성 / 파괴주기보다는 제한된 기존 요소 세트를 사용합니다. 이 방법을 사용하면 무한 스크롤을 실제로 구현할 수 있습니다 .

Ionic을 사용하여 / hack / adapt collectionRepeat또는 이와 유사한 도구 를 사용할 필요는 없습니다 . 이것이 그들이 오픈 소스라고 부르는 이유입니다. 🙂 (이온 팀은주의를 기울일만한 아주 독창적 인 일을하고 있습니다.)


React에서 매우 비슷한 것을하는 훌륭한 예가 적어도 하나 있습니다. 업데이트 된 컨텐츠가있는 요소를 재활용하는 대신 트리에서 보이지 않는 것을 렌더링하지 않기로 선택하는 것입니다. 매우 간단한 POC 구현으로 약간의 깜박임이 허용되지만 5000 항목에서 빠르게 타 오르고 있습니다 …


또한 … 다른 게시물 중 일부를 반향하려면 track by작은 데이터 세트에서도 사용하는 것이 매우 유용합니다. 필수라고 생각하십시오.


답변

나는 이것을 볼 것을 권장합니다 :

AngularJS 최적화 : 1200ms ~ 35ms

그들은 네 부분으로 ng-repeat를 최적화함으로써 새로운 지시를 내 렸습니다.

최적화 # 1 : 캐시 DOM 요소

최적화 # 2 : 집계 감시자

최적화 # 3 : 요소 생성 지연

최적화 # 4 : 숨겨진 요소에 대한 감시자 우회

프로젝트는 github에 있습니다.

용법:

1-이 파일들을 단일 페이지 앱에 포함 시키십시오 :

  • core.js
  • scalyr.js
  • slyEvaluate.js
  • slyRepeat.js

2- 모듈 의존성 추가 :

var app = angular.module("app", ['sly']);

3- ng-repeat 교체

<tr sly-repeat="m in rows"> .....<tr>

즐겨!


답변

트랙 바이 및 더 작은 루프와 같은 위의 모든 힌트 외에도이 힌트는 많은 도움이되었습니다.

<span ng-bind="::stock.name"></span>

이 코드는 일단로드되면 이름을 인쇄하고 그 후에는 그 이름을 보지 않습니다. 마찬가지로 ng-repeats의 경우 다음과 같이 사용할 수 있습니다.

<div ng-repeat="stock in ::ctrl.stocks">{{::stock.name}}</div>

그러나 AngularJS 버전 1.3 이상에서만 작동합니다. 에서
http://www.befundoo.com/blog/optimizing-ng-repeat-in-angularjs/


답변

“추적”을 사용하여 성능을 향상시킬 수 있습니다.

<div ng-repeat="a in arr track by a.trackingKey">

보다 빠른:

<div ng-repeat="a in arr">

심판 : https://www.airpair.com/angularjs/posts/angularjs-performance-large-applications


답변

모든 행의 높이가 동일한 경우 가상화 ng-repeat를 확인해야합니다. http://kamilkp.github.io/angular-vs-repeat/

데모 는 매우 유망 해 보이며 관성 스크롤을 지원합니다.


답변

규칙 1 : 사용자가 아무것도 기다리지 않도록하십시오.

빈 화면이 나타나기 전에 3 초를 기다리는 것보다 10 초가 걸리는 수명이 늘어나는 페이지가 더 빨리 나타나고 한 번에 모두 얻을 수 있습니다.

따라서 페이지를 빠르게 만드는 대신 최종 결과가 느리더라도 페이지 를 빠르게 표시 하십시오 .

function applyItemlist(items){
    var item = items.shift();
    if(item){
        $timeout(function(){
            $scope.items.push(item);
            applyItemlist(items);
        }, 0); // <-- try a little gap of 10ms
    }
}

위의 코드는 목록이 행 단위로 증가하는 것으로 보이며 항상 한 번에 렌더링하는 것보다 항상 느립니다. 그러나 사용자 에게는 더 빠릅니다.