简体   繁体   中英

Angular2 Change Detection Infinite Loop

We have a simple component with an input property as such:

<app-example [exampleInput$]="exampleInputData$"></app-example>

On the component where we use app-example we have:

get exampleInputData$(): any {
    var subject = new Subject<string>();
    console.log("Log1");

    this.exampleService.getAllData(this.id).subscribe(data => {
      console.log("Log2");
      subject.next(data);
    });

    return subject.asObservable();
  }

And the exampleService is a simple observable as such:

public getAllData(id): Observable<ExampleObject[]> {
    return this.http.get(`${this.baseUrl}data/${id}`).map((response: Response) => {
      var data = <ExampleObject[]>response.json();
      return data;
    }).catch(this.handleError);
  }

When we run this it get's into an infinite loop, if we change the changeDetection to OnPush it stops or if we remove the call to getAllData . Does anyone have an idea of why this is causing an infinite loop?

Below is the app-example component and the HTML template:

export class ExampleComponent implements OnDestroy {      
  private subscription: ISubscription;
  private parsedResponse : any;

  @Input() exampleInput$;

  getData(): void
  {    
    this.subscription = this.exampleInput$.subscribe((data) => {this.parsedResponse = data;},
      () => {
        // Here we download the data as CSV
      });
  }

  ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }

Template:

<button class="btn btn-primary" (click)="getData()">
  Download As CSV
</button>

You are binding a method in the HTML. So in every change detection the method will be invoked. You need to set the observable like an attribute and the content in the exampleInputData$() put it in ngOnInit

export AppComponent {

    subject = new Subject<string>();
    observable$ = subject.asObservable();
    id: number;

    ngOnInit() {
        // I expected you know how to get the id value
        this.exampleService.getAllData(this.id).subscribe(data => {
            this.subject.next(data);
        });
    }
}

And the HTML

<app-example [exampleInput$]="observable$"></app-example>

I don't know how the rest of your code goes, but I think you may be calling exampleInputData$ in each render, you should do something like this:

Class Component implements OnInit {
    constructor(exampleInputDataService: ExampleInputDataService) {
    }

    ngOnInit(): void {
        this.data = this.exampleInputDataService.getData();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM