What is the performance impact for a class / interface with a lot of fields?
Asked Answered
I

1

8

I have a class (interface) in my angular 4 app which has a lot of fields. Note that the instance of this class/interface is immutable (i.e. the members will NEVER be changed).

E.g.

public interface IHaveALotOfFields {
    field1: string;
    //...
    field500: string;
}

This interface is provided via a (singleton / application level provided) service which exposes the class as a member. E.g.

@Injectable()
public class MyService {
    public translations: ITranslationsProvider;
}

The service is injected into a lot of components (almost all components) and often used in their corresponding template and often also in the ts-part of the component. E.g.

@Component({
               template: `Value: {{service.field500}}`
           })
export class MyComponent {
    public constructor(public service: MyService) {
    }

    private doSomething(): string {
        return this.service.field1;
    }
}

Now my questions:

  • Will a big class (with a lot of fields) make angular slow because of the change detection?
  • Is there any way to mark a class as "Ignore me on change detection"? (something similar to ChangeDetectionStrategy.OnPush, but instead of specifying this for each component, can be declared on the class itself or on the member of the service)

Please note that I don't want to change the change-detection strategy of all my components to OnPush.

Isotonic answered 17/7, 2017 at 13:23 Comment(3)
The interface is just a way of type checking. It won't get injected... Only objects get injected that have been instantiated by new for a classes. An Interface is a contract the class will adhere to. In the interface you assign properties and method signatures for the contract... Services have @Injectable and Angular takes care of instantiation of those for you automatically wiring things together.Boomer
I know. I have concrete classes which implement this interface. The MyService basically gets an instance of a class which implements the interface injected.Parrish
The interface is not injected only objects.. This is what I was hoping to help you with. i.e. You can't do new on an interface...Boomer
A
4

Will a big class (with a lot of fields) make angular slow because of the change detection?

No. Angular change detection performs two operations that read class properties:

  • DOM update on the current component
  • input bindings update of child components/directives

For these operations Angular compiler creates two functions:

  • updateRenderer - reads fields used in the template
  • updateDirectives - read fields specified in input binding expressions

These functions read only specific properties from the service. For your example

Value: {{service.field500}}

the updateRenderer function will look something along the lines:

function(_ck,_v) {
    var _co = _v.component;
    var currVal_0 = _co.service.field500;
    _ck(_v,1,0,currVal_0);

These functions are called on each digest loop. But as you can see only the relevant property will be read from the service. So it doesn't matter how many properties there are on the service.

Is there any way to mark a class as "Ignore me on change detection"?

I assume you're asking about one-time binding like we had in AngularJS. Maybe it will be added in Angular as well. I'll be monitoring that and update the answer if something comes up. But as you probably know you can disable/enable change detection for the component using cd.detach/cd.attach. You can listen for some signal from the service and run cd manually when neeed.

Here is the list of articles you could read to understand the mechanics of change detection better:

Aryl answered 21/7, 2017 at 8:34 Comment(4)
Thanks for the great answer. What I mean with the way to mark a class as "Ignore me on change detection" is,if there is a way to tell angular that properties/fields of this specific class are "constant" (have constant values) and will never change. No matter if the class was injected from a service or as an input or however else.Parrish
@OschtärEi, ah, I see. No, unfortunately there's no way yet to do that. In AngularJS we had one-time binding. Maybe it will be added in Angular as well. I'll be monitoring that and update the answer if something comes up. But as you probably know you can disable/enable change detection for the component using cd.detach/cd.attach. You can listen for some signal from the service and run cd manually when neeed.Aryl
Thanks again. But if i use detach/attach all the change detection of the component will be detached (what I don't want) and also I would need to do this in all my components (since almost all components use this "big class" (it's for translations).Parrish
@OschtärEi, I understand. As I said, there's nothing else you can do for now.Aryl

© 2022 - 2024 — McMap. All rights reserved.