Yoamb
Yoamb

Reputation: 485

How can I be sure a constructor function only runs once?

Is there any way for this code in the constructor of my service TranslatorService is calling just one time for all application or on demande, and not all time homecomponent is load ????

this.translations$ = translationsCollection.snapshotChanges().map(actions => {
      return actions.map(a => {
        ...
      })

translation class for my translate retrive from firestore ex:

{
  "WELCOME": {
   "FR": "bienvenue",
   "GB": "Welcome"
 }
}

export interface Translation {
    [code: string]: TranslationInfo;

}

export interface TranslationInfo {
    [language: string]: string;
}

my core module

import { NgModule } from '@angular/core';
import { AuthService } from './auth.service';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AngularFirestoreModule } from 'angularfire2/firestore';
import { TranslatorService } from '../services/translator.service';
@NgModule({
imports: [
    AngularFireAuthModule,
    AngularFirestoreModule
],
providers: [AuthService, TranslatorService]
})
export class CoreModule { }

injected in appmodule

@NgModule({
declarations: [
...

],
imports: [
...
    CoreModule,
...
],
providers: [AuthGuard],
bootstrap: [AppComponent]
})
export class AppModule { }

my translator service

    @Injectable()
export class TranslatorService {

  translationsCollection: AngularFirestoreCollection<Translation>;
  translations$: Observable<any>;
  public translations: Translation[];

  constructor(private afs: AngularFirestore) {
    var translationsCollection = this.afs.collection("translations");
    this.translations$ = translationsCollection.snapshotChanges().map(actions => {
      return actions.map(a => {
        ...
      })
    });

my component

    export class HomeComponent implements OnInit {
translations$: Observable<any>;
constructor(private translator: TranslatorService) { }

ngOnInit() {
    this.translations$ = this.translator.translations$;
}

my component view

<div *ngFor="let translation of translations$|async">
<pre>{{translation | json}}</pre>
</div>

Upvotes: 0

Views: 64

Answers (2)

Brandon
Brandon

Reputation: 39182

Just use a singleton pattern: move the code to a static function and store its result in a static field. The constructor just calls the static function which will check the field before running its code:

export class TranslatorService {

  translationsCollection: AngularFirestoreCollection<Translation>;
  translations$: Observable<any>;

  static tCollection : AngularFirestoreCollection<Translation>;
  static t$: Observable<any>;
  static initialize(afs: AngularFireStore) : void {
    if (TranslatorService.tCollection == null) {
      TranslatorService.tCollection = afs.collection("translations");
      TranslatorService.t$ = TranslatorService.tCollection.snapshotChanges().map(actions => actions.map(a => ...));
    }
  }

  public translations: Translation[];

  constructor(private afs: AngularFirestore) {
    TranslatorService.initialize(this.afs);
    this.translations$ = TranslatorService.t$;
    this.translationsCollection = TranslatorService.tCollection;
  }
}

Upvotes: 2

user2842256
user2842256

Reputation: 81

I have done something similar in one of my projects. You just need to move your translation code one level above. i.e.

Make a component called translation component which wraps all the components and put your logic in it. That way it will be loaded only once through the application life cycle.

You route config should then look something as follows:

const routes: Routes = [
    {
        path: '', component: LanguageComponent,
        children: [
            { path: '', component: HomeComponent },
            { path: 'login', component: LoginComponent },
        ]
    }
];

Basically all your application is wrapped into Language component.

Upvotes: 0

Related Questions