1

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.

Emil Alkalay
  • 426
  • 4
  • 15
  • 1
    Did you look at `NgFor` source code? There is `NgDoCheck` hook where is called `differ.diff()` where is called `DefaultIterableDiffer.check` and finally is called `trackByFn` function in for loop statement. `NgDoCheck` is called during every change detection run. – yurzui Dec 19 '16 at 15:10
  • This is good direction. So why NgDoCheck is called when I scroll. If angular2-infinite-scroll is firing so many checks on scroll, is that a performance problem? – Emil Alkalay Dec 19 '16 at 15:17
  • 1
    https://github.com/orizens/angular2-infinite-scroll/blob/8543ef7344a64ceaf7617d1953f98adae3595092/src/scroller.ts#L135 – yurzui Dec 19 '16 at 15:22
  • I investigated the code. It looks like there is nothing which is a surprise. I'm surprized what happens when the container is subscribed for scroll event. It looks like a lot of events are fired on one scroll operation. – Emil Alkalay Dec 19 '16 at 16:36

1 Answers1

1

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.

Emil Alkalay
  • 426
  • 4
  • 15