Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function gets called several times

Tags:

angular

ngfor

I want to display a dataList. Some values are calculate from a function. It seems angular2 calls the calculate function many times.

  <tr *ngFor="let data of dataList">
    <td>{{ data.no }}</td>
    <td>{{ data.name }}</td>
    <td>{{ calculateFunction(data.price) }}</td>
  </tr>

Console will output "calculate..." many times, more than dataList.length.

calculateFunction() {
  console.log('calculate...');
  return ...;
}

Should I worry about that for performance or just let angular2 do this?

like image 966
user7395677 Avatar asked Jul 20 '17 06:07

user7395677


People also ask

Can a function be called multiple times in C?

We pass arguments in a function, we can pass no arguments at all, single arguments or multiple arguments to a function and can call the function multiple times.

Can a function be called multiple times?

In order to run a function multiple times after a fixed amount of time, we are using few functions. setInterval() Method: This method calls a function at specified intervals(in ms). This method will call continuously the function until clearInterval() is run, or the window is closed.

When two functions call each other repeatedly it is known as?

In Indirect recursive functions, two functions mutually call each other wherein both the functions must have a base case. Let's understand using a flowchart. Here, function1 calls function2 which in turn calls function2 which calls the first function. This can be explained using an example.


2 Answers

The caculateFunction(data.price) function will be called every time Angular runs change detection for the component (more precisely for the embedded view created by ngFor). This is because updating DOM is part of change detection and Angular needs to call caculateFunction to know what value to use for DOM update. And change detection cycle can run quite often. So if you have 3 items in the list and CD is triggered 3 times initially, you will see that the function is called 9 times.

If you inspect the updateRenderer function, you shoul see something along these lines:

function(_ck,_v) {
    var _co = _v.component;
    var currVal_0 = _co.calculateFunction(_v.context.$implicit);
    _ck(_v,3,0,currVal_0);
  }

Read more about how Angular updates DOM in The mechanics of DOM updates in Angular.

Should I worry about that for performance or just let angular2 do this?

If calculateFunction(data.price) returns the same result for the same price, it's better to calculate these values beforehand for each item and simply renderer them in the template.

<td>{{ data.no }}</td>
<td>{{ data.name }}</td>
<td>{{ data.calculatePrice) }}</t

In this way you will avoid performance decreasing function calls.

like image 159
Max Koretskyi Avatar answered Sep 19 '22 12:09

Max Koretskyi


you can change the components changeDetectionStrategy to onPush. after that, your calculateFunction function does not call several times.

to do that :

in your component:

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css'],
 changeDetection: ChangeDetectionStrategy.OnPush // this line
})

export class AppComponent {

  ....

  calculateFunction(value) {
    console.log('calculate...');
    return ...;
  }
}

and in your app.component.html :

 <tr *ngFor="let data of dataList">
  <td>{{ data.no }}</td>
  <td>{{ data.name }}</td>
  <td>{{ calculateFunction(data.price) }}</td>
 </tr>

UPDATED

The best way to handle this scenario is to use Pipe, like the following :

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'handlePrice'
})
export class HandlePricePipe implements PipeTransform {
  transform(price: number): number {
    console.log('In Pipe ....');
    return price * 2;
  }
}

Then use that :

<tr *ngFor="let data of dataList">
   <td>{{ data.no }}</td>
   <td>{{ data.name }}</td>
   <td>{{ data.price |handlePrice }}</td>
</tr>
like image 23
AbolfazlR Avatar answered Sep 21 '22 12:09

AbolfazlR