Initiating Angular APP_INITIALIZERThe Angular APP_INITIALIZER

I am a newcomer to Angular and currently utilizing Angular6 for development purposes. I have a specific query regarding my app. Before the app initializes, I need to invoke three services that provide configurations required by the app. Let's refer to these services as Initialization, Config, and UserDetails. To facilitate this, I have included these services in the app-module.ts file as shown below.

`

    export function initializeApp(initService: InitializationService) {
        return () => initService.getInit();
    }

    export function fetchSettings(configService: ConfigService) {
        return () => configService.getConfig();
    }
export function retrieveUserSettings(userDetails: UserDetailsService) {
        return () => userDetails.getSettings();
    }

    @NgModule({
      imports: [/*my-imports*/],
      providers: [
        AppLoadService,
        { provide: APP_INITIALIZER, useFactory: initializeApp, deps: [InitializationService], multi: true },
        { provide: APP_INITIALIZER, useFactory: fetchSettings, deps: [ConfigService], multi: true },
        { provide: APP_INITIALIZER, useFactory: retrieveUserSettings, deps: [UserDetailsService], multi: true }
      ]
    })

` The InitializationService contains values necessary for the proper functioning of the other two services. The service requests are sent immediately during app initialization. I require the ConfigService and UserDetailsService to be invoked only after the InitializationService call is completed. To address this, I have implemented the following,

// AppConfig.ts

export class AppConfig {
  public static Config= {};

  public static $subject = new Subject();
}

// InitializationService

getInit () {

const promise = new Promise((resolve, reject) => {
      this.http.get().then(val => {
        AppConfig.config = val;
        AppConfig.$subject.next(val);
      });
};

return promise;
}

//ConfigService

getConfig () {
 if(AppConfig.Config.baseUrl === undefined) {
   AppConfig.$subject.subscribe(val => {
     this.http.get(AppConfig.Config.baseUrl).then(//doSomething);
   })
 }
}

A static subject is created and subscribed to in order to coordinate the sequence of calls. Once the InitializationService completes, it emits the next value for the subject, which is then observed by the ConfigService. Upon receiving the subscribed call, further operations are carried out. The same implementation is duplicated for the UserDetails getSettings() method.

Is my approach correct? Have you experimented with any other proven patterns?

Any suggestions or better approaches to handle the above scenario would be greatly appreciated.

Thank you in advance.

Best regards, hawx

Answer №1

Streamline the initialization process with a single initializer:

export function initializeAll(initService: InitializationService, configService: ConfigService, userDetails: UserDetailsService) {
  return () => {
    return initService.getInit().pipe(
      switchMap(() => {
        return flatMap([ConfigService.getConfig(), userDetails.getSettings()]);
      }),
    );
  }
}

Keep in mind that using flatMap assumes that both operations are completed before proceeding. This is just one way to handle it. With rxjs operators, you have complete control over the process and only need one APP_INITIALIZER.

Answer №2

//app-module code

export function initializeApplication(appInitializer:AppInitializer, configurationService:ConfigurationService) {
  // We return a promise as required by the app_init token. There is an ongoing issue with Angular regarding this: https://github.com/angular/angular/issues/15088
  return () => {
    const promise = new Promise((resolve, reject) => {
      appInitializer.load().then(() => {
        configurationService.fetch().then(() => {
          resolve();
        });
      });
    });
    return promise;
  }
}

//appInitializer.load() call

const promise = this.http.get<any>(`myConfigURL`).toPromise();
promise.then(response => {
 Object.assign(AppConfiguration.ENV, response.value.parameters);
});
return promise;

// configuration service call

const promise = this.http.get<any>(myConfigUrl).toPromise();
promise.then(response => {
  //process response data
});
return promise;

I opted for this approach to address the issue with managing Subject and due to time constraints preventing me from troubleshooting the Observable problems.

Thank you for your input.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most effective way to refresh SCSS in a current Angular project?

I'm in the process of updating the SCSS version within my angular project. From the beginning, I selected scss in the angular cli for this project, so I have been using SCSS already. However, now I need to incorporate a spacing library that requires t ...

Utilize a personalized npm script to change the name of a file

I need some help with creating a script for my angular2 project that will rename README.md to README_2.md. After installing "renamer" : "0.6.1", I tried making this script: "renameMd": "renamer --find js/README.md --replace js/README_2.md" in my package.j ...

MUI provides the flexibility to adjust the opacity separately for Chip labels/icons and backgrounds

My objective is to customize the opacity of label/icon and background in MUI Chip. I want the label & icon to have an opacity of 1, while the background should have an opacity of 0.0571. Technologies used in this project include React, TypeScript, Materia ...

How to incorporate a popup modal in your project and where should you place the DialogService constructor

Currently, I am in the process of developing a CRUD ASP.NET Core application using Angular 2 and Typescript. Prior to incorporating a popup feature, this was my output: https://i.stack.imgur.com/vHvCC.png My current task involves placing the "Insert or e ...

An unfamiliar data type is provided as a number but is treated as a string that behaves like a number

Here is the code snippet in question: let myVar = unknown; myVar = 5; console.log((myVar as string) + 5); Upon running this code, it surprisingly outputs 10 instead of what I expected to be 55. Can someone help me understand why? ...

Is it possible to utilize ion-input's form validation while utilizing an HTML pattern for input?

I am working on validating an ion-input using a regex pattern in the HTML code. The purpose of this is to only allow numbers from 0 to 24 as input. Currently, this validation is functioning correctly and displays an error message if an incorrect number or ...

TS2304: The build process is unable to locate the name 'iterable' within @types

As an experienced dog attempting to master new tricks like npm and TypeScript, I find myself faced with a challenge in my Visual Studio 2017 project. Despite setting it to "Latest" TypeScript 2.5 and adding @types/jquery (3.2.12), the project keeps throwin ...

Error loading ngs-boostrap in angular2: issues encountered during initialization

Attempting to implement a dropdown menu using ng2-bootstrap component, but encountering an error upon access: Error message received: Failed to load resource: the server responded with a status of 404 (Not Found) Steps taken so far: 1) Installed ng2-boo ...

Updating documents within an array in MongoDB is a common task that can be easily accomplished

Trying to modify a specific property within my MongoDB document. This is how the document is structured: "_id" : ObjectId("57e2645e11c979157400046e"), "id" : 1651570992420, "creator" : "nameHere ...

What is the best way to transform an array of objects into a nested array through shuffling

I am dealing with a diverse array of objects, each structured in a specific way: data = [ { content: { ..., depth: 1 }, subContent: [] }, { content: { ..., depth: 2 ...

Using kotlinx.serialization to deserialize a JSON array into a sealed class

Stored as nested JSON arrays, my data is in rich text format. The plaintext of the string and annotations describing the formatting are stored in text tokens. At decode time, I aim to map the specific structure of these nested JSON arrays to a rich Kotlin ...

Showcase Ionic Validation - exhibit error messages reminiscent of material design

I've been working on a Login and Registration Page in Ionic 5. I wanted to showcase error messages beneath the input text field like shown in this example https://i.stack.imgur.com/d83ZV.png Thus, I integrated Angular Responsive Forms into my projec ...

Encountering a "breaks the Content Security Policy directive: 'default-src 'none''" message while trying to deploy an Angular application on Heroku

I've been encountering difficulties while attempting to deploy my Angular app on Heroku. An error message keeps popping up stating that the image '' violates the Content Security Policy directive: "default-src 'none'". Even though ...

The ViewChild element is not defined

Check out the code snippet below. // ... @ViewChild('searchBar', {static: false}) searchBar: IonSearchbar; @ViewChild('locations', {static: false}) locationsList: IonList; // ... ngAfterViewInit() { this.searchBarInputSub ...

Unable to connect a unique FormGroup (using ControlValueAccessor) within a FormArray

We are working with two components, referred to as parent and child, both implementing ControlValueAccessor. The parent form is defined as follows: this.formBuilder.group({ children: this.formBuilder.array([]) }) While the child form looks like this: ...

Utilizing Omit for the exclusion of nested properties within a TypeScript interface

One of the components in a library I am using is defined like this: export interface LogoBoxProps { img: React.ReactElement<HTMLImageElement>, srText?: string, href?: LinkProps['href'] } export type LogoBoxType = React.FC<React.HT ...

Converting React to Typescript and refactoring it leads to an issue where the property 'readOnly' is not recognized on the type 'IntrinsicAttributes & InputProps & { children?: ReactNode; }'

I'm currently in the process of refactoring an application using Typescript. Everything is going smoothly except for one particular component. I am utilizing the Input component from the library material-ui. import {Input} from "material-ui"; class ...

Angular HttpClient request fails to initiate

Overview: A button click on a form triggers the methodForm within the component. methodForm then calls methodService in the service layer. methodService is supposed to make an HTTP POST request. Problem: The HTTP POST request is not being made. However, me ...

What is the best way to mandate the declaration or type of a function in TypeScript?

Let me present my dilemma: I am aiming to create a declaration file containing TypeScript function models. This file will be utilized by various individuals to build their own programs. To achieve this, I have crafted a def.d.ts file with a small example ...

Enabling the "allowUnreachableCode" Compiler Option in Visual Studio 2015 Triggers "JsErrorScriptException (0x3001)" Issue

We've implemented TypeScript in our Visual Studio 2015 (Update 2) setup for a non-ASP.Net project consisting of pure HTML and JavaScript. In order to disable the 'allowUnreachableCode' option, we made adjustments in the tsconfig file. It&apo ...