1

The answers on this topic I found are about 7 years old. In summary, it's recommended to use constructor for basic property initialization, setup Dependencies Injection and tasks which are not to complex. Use ngOnInit for more complex initialization that involves interaction with services as http requests, @Input communication mechanism, or other Angular-specific operations.

Now it's recommended to use new inject function to handle angular DI, because you may encounter issues with es2022. Are the following code snippets are only a question of style or is there any other difference?

export class ExampleComponent {
    private service = inject(Dependency);
            
    }


export class ExampleComponent {
    private service: Dependency;
    
    constructor( ) { 
      this.service = inject(Dependency);            
    }

Is it recommended to pass a subscriber function inside the constructor or is this operation also a complex thing that should be defined inside ngOnInit function?

export class ExampleComponent {
    private subscription: Subscription;
    private service = inject(Dependency);

    constructor( ) { 
      this.subscription = this.service.getAnObservable().subscribe(result => {
      //do something on result
      });
    }
Hölderlin
  • 424
  • 1
  • 3
  • 16

1 Answers1

1

In old typescript, the initialization of properties is, under the covers, moved to the beginning of the constructor code.

In ES2022 the initialization of properties is done before the constructor, not within it.

So your examples don't have a difference, and even

export class ExampleComponent {
  private service = inject(Dependency);
  private widget = this.service.getWidget();
}

and

export class ExampleComponent {
  private service: Dependency;
  private widget;

  constructor( ) { 
    this.service = inject(Dependency);
    this.widget = this.service.getWidget();
  }
}

are future-proof but

export class ExampleComponent {
  private widget = this.service.getWidget();

  constructor(private service: Dependency) {}
}

probably won't work in the future but it works today because Typescript currently initializes widget inside the constructor.

As a rule, I set up observables in the constructor, but observers in ngOnInit. The way I think of it, observables are just plumbing. Until subscribed to, nothing is flowing. In contrast, before you subscribe or otherwise add an observer your component must be set up and ready to go! This helps avoid bugs where the code is waiting for a value that was streamed/emitted before all the plumbing was in place.

JSmart523
  • 2,069
  • 1
  • 7
  • 17
  • btw: If I assign subscription in ngOnInit I need definite assignment assertions or `private subscription: Subscription | undefined;`. If TypeScript wants everything to be initialized in the constructor, how can I express this without using the "!"? Is there a pattern? – Hölderlin Aug 12 '23 at 08:09
  • Is `export class ExampleComponent { private widget; constructor(private service: Dependency) { this.widget = service.getWidget(); } } ` also future-proof? – Hölderlin Aug 12 '23 at 08:12
  • Yes I think that's future -proof. – JSmart523 Aug 12 '23 at 12:29
  • Re "btw:", why do you have a subscription? If you can, the best pattern is to define observables without subscribing, then using the async pipe in the HTML template. Otherwise, I use `private _destroy$: Subject = new Subject(); – JSmart523 Aug 12 '23 at 12:35
  • Oops, premature send. Re "btw:", why do you have a subscription? If you can, the best pattern is to define observables without subscribing, then using the async pipe in the HTML template. Otherwise, I use `private _destroy$: Subject = new Subject(); ngOnDestroy() { const d$ = this._destroy$; if (d$) { d$.next(); d$.complete(); } }` and then have all observables `.pipe(takeUntil(this.destroy$))` This way I don't need to manage subscriptions at all. – JSmart523 Aug 12 '23 at 12:41
  • "why do you have a subscription?" In the case where I want to exchange data between components (e.g. via service), where the value of data (subject) is dynamic and the other component has to listen (observe) for change. – Hölderlin Aug 13 '23 at 09:46