angular2-infinite-scroll and ng-for trackBy function

1.5k views Asked by At

I'm using angular2-infinite-scroll combined with trackBy ng-for function. I noticed very strange behavior, which I can not understand. I had put console.log statement in my trackBy function and I noticed that when I scroll, the log is is executed hundreds of times.

This is something that concerns me and I can not find anything about that behavior.Here is an example:

https://plnkr.co/edit/k3YduRtqyXd0TNoPXwiQ?p=preview

//our root app component
import {Component} from '@angular/core'

@Component({
  selector: 'my-app',
  styles: [`
    .search-results {
      height: 100%;
      // overflow: scroll;
    }
    .title {
      position: fixed;
      top: 0;
      left: 0;
      background-color: rgba(0,0,0,.5);
      color: white;
      width: 100%;
    }
    .title small {
      color: #eaeaea;
    }
  `],
  template: `
    <h1 class="title well">{{ title }} <small>items: {{sum}}</small></h1>
    <div class="search-results"
         infinite-scroll
         [infiniteScrollDistance]="scrollDistance"
         [infiniteScrollThrottle]="throttle"
         (scrolled)="onScrollDown()">
      <p *ngFor="let i of array; trackBy: test">
        {{ i }}
      </p>
    </div>
  `
})
export class AppComponent {
  array = [];
  sum = 100;
  throttle = 300;
  scrollDistance = 1;
  title = 'Hello InfiniteScroll v0.2.8, Ng2 Final';

  constructor() {
    this.addItems(0, this.sum)
  }
  test(index, test){
    console.log('test');
  }
  addItems(startIndex, endIndex) {
    for (let i = 0; i < this.sum; ++i) {
      this.array.push([i, ' ', this.generateWord()].join(''));
    }
  }
  onScrollDown () {
    console.log('scrolled!!');

    // add another 20 items
    const start = this.sum;
    this.sum += 20;
    this.addItems(start, this.sum);
  }

  generateWord() {
    return chance.word();
  }
}

I would appreciate any explanation about that.

1

There are 1 answers

0
Emil Alkalay On BEST ANSWER

I think I found the answer: In an Angular 2 app, zone.js basically polyfills/overrides native functions like addEventListener, setTimeout etc.

When event listeners are added using addEventListener function, they get registered in the zone.js and effectively are used to detect changes inside the app. This will most likely cause performance issues. Reference: https://www.bountysource.com/issues/34114696-event-listeners-should-be-registered-outside-angular.

In addition subscription to scroll event is the same as .addEventListener('scroll'), which triggers events while scroll happens. This causes a lot of ngDoCheck calls, which trigger trackBy recalculation. This is could create performance issues related with angular2-infinite-scroll.

P.S. I would accept any other explanations which are better then mine or give is guidelines how to resolve possible performance issues or avoid them in future.