Why is this / gettor method called X times in Angular 2 service

I am trying to associate a value in my HTML component with a property in a service. If the private variable is null, it should exit and get the value from the HTTP call.

However, I noticed that as soon as I get attached to the gettor property in my HTML component, it fires several times.

I simplified an example: this Plunker

get Item(): string { console.log("Item()", this._item); return this._item; } 

Open a console and watch the multiple exits of "Item () Initiated." I expected to hit him only once. (the result will be the same as with the method instead of getter). If I use the Gettor method with the click method, it runs only once.

+5
source share
2 answers

This is because the html-related value must be evaluated every time something โ€œchangesโ€ in the application, so if the value of the linked element has changed, it will be reflected in html, which will give you this magical autoupdating binding. This is probably what you want 90% of the time, since you don't want to worry about notifying angular to update the value of the associated property.

If you have some kind of heavy logic in getter or you want to control when the value will be updated, you can change the changeDetectionStrategy components to onPush, for example, in this plunger .

 @Component({ selector: 'my-app', template: ` <div><button (click)="_service.ShowItem()">Show Item</button></div> <div>{{_service.Item}}</div> `, providers: [ Service ], changeDetection: ChangeDetectionStrategy.OnPush }) 

There is a great explanation on how angular2 works with thoughtram change detection

This is similar to saying: "Do not check this component when changes are detected, I will let you know when to check it."

Then you can use a service called ChangeDetectorRef to mark the component for change detection.

For http, what you want to do is have a trigger to make an http call, and then get the desired value from the response and "cache" it somewhere so that you can bind it to the user interface. The trigger can be varied, depending on your case, for example. interval, recursion, button, etc.

+9
source

The accepted answer is amazing and really explains everything. However, as he said in 90% of cases, you will not want to change the method of detecting changes. So I have a simple, albeit ugly, workaround that I thought I would share when you go to the database to get some data and don't want to hit the API several times in a row. It will return a null object until the data goes down. Make sure you use * ngIf in your template as needed.

 private __itemHit: number = 0; private __item: string; get Item(): string { if(!this.__item && this.__itemHit == 0){ this.__itemHit = 1; //Your data fetch is likely different than the way I do mine. apiService.Post(url, body, option).subscribe((response) => { this.__item = response.Result;}); console.log("Item()", this._item); } return this._item; } 
+1
source

Source: https://habr.com/ru/post/1260370/


All Articles