Dealing with Dependency Injection Problem in Angular 6

I am grappling with a challenge in my cross-platform Angular application. The crux of the issue is determining the platform on which the app is running and accordingly injecting services. Below is how I've structured it:

@NgModule({
  providers: [
    ConfigService,
     {
       provide: APP_INITIALIZER,
       useFactory: configFactory,
       deps: [ConfigService],
       multi: true
    },
    {
      provide: UserService,
      useFactory: userServiceFactory,
      deps: [
        ConfigService
      ],
      multi: true
    },

  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

The configFactory function returns a Promise:

export function configFactory(configService: ConfigService): () => Promise<any> {
  return (): Promise<any> => {
    return new Promise(resolve => {
       Device.getInfo().then(info => {
          configService.platform = info.platform; // can be either 'ios' or 'web'
       });
    });
  }
}

The value of configService.platform is crucial for deciding the type of UserService provider to use, hence the need for the userServiceFactory method:

const userServiceFactory = (configService: ConfigService): any=> {
    if(configService.platform === 'ios') {
        return new UserServiceDevice()
    } else {
        return new UserWebServiceWeb();
    }
  }

Although the config service initialization works correctly, the userServiceFactory function runs before the configFactory function has finished executing, resulting in config.platform being undefined. It seems like it does not wait for the configFactory function to resolve despite ConfigService being set as a dependency. How can I address this? Are there better approaches to handle such scenarios?

Answer №1

Why not enhance the flexibility of the service itself rather than trying to solve everything during module instantiation? Although this may not directly address your initial question, it could potentially resolve your issue.

Check out the enhanced UserService implementation:

class PlatformAgnosticUserService implements IUserService {
   private service: IUserService;

   constructor(
      private _PLAT : Platform,
      private mobileUserService: MobileUserService,
      private webUserService: WebUserService
   ) {
      if (this._PLAT.is('ios') || this._PLAT.is('android'))
      {
         this.service = mobileUserService;
      }
      else
      {
         this.service = webUserService;
      }
   }

   userCreate(param: any) {
      this.service.userCreate(param);
   }

}

Although it may not be as elegant, it's the best solution I could come up with. Cheers!

Previous Answer Below

You might be over-complicating things. Consider simplifying to this:

@NgModule({
  providers: [
    {
      provide: UserService,
      useFactory: userServiceFactory,
      deps: [],
      multi: true
    },

  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

And also consider this modification:

    const growerServiceFactory = (configService: ConfigService): () => Promise<any> => {
return (): Promise<any> => {
    return new Promise(
       resolve => {
         Device.getInfo().then(info => {
            return new UserServiceDevice();
       },
       () => {
         return new UserWebServiceWeb()
       });
    });
  }

If you're not using the config service for anything else, you can possibly skip it in this case.

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

When using Angular's `createComponent()` method, an error may be thrown with the message "ERROR TypeError: Cannot add

I am currently working on a project where I am dynamically creating components. The component's class is being passed via an ngrx action and the process involves: loadComponent(componentType: Type<any>): void { const viewContainerRef = this.co ...

Encountering issues with FlexLayoutModule in Angular 11

After adding the FlexLayoutModule and including it in my project, I encountered the following error: Error: node_modules/@angular/flex-layout/typings/module.d.ts:16:22 - error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved ...

How to utilize Enzyme to call a React prop in TypeScript

I'm currently in the process of converting my Jest tests from Enzyme to TypeScript, and I've come across a specific case that I'm unsure how to resolve. Essentially, I'm attempting to invoke a function passed as a prop to a sub-componen ...

What impact does setting 'pathmatch: full' in Angular have on the application?

When the 'pathmatch' is set to 'full' and I try to delete it, the app no longer loads or runs properly. import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { H ...

Guide to creating animations with javascript/react js

My attempt at altering the opacity of an element every 100 milliseconds following a click event has not been successful. The function change is triggered by a click, yet the code does not work as intended. Here's what I have so far: function change (i ...

Utilizing *ngfor in Angular 7 to Group and Display Data

I currently have incoming data structured like this in my Angular application Visit this link to see the data format https://i.stack.imgur.com/jgEIw.png What is the best way to group and sort the data by State and County, and present it in a table as sh ...

Angular Service Singleton Utilized in Components

I have a structural question regarding my Angular application. I am following the widely-used core, shared, and feature modules structure, similar to the one found here. In my core module, I have a singleton notification service defined, but I use a custom ...

Testing an Angular Service method that involves a window.location.replace operation

I'm currently working on an Angular 4 application and I am facing a challenge with testing a method of a Service. This method calls a private method within the same service that includes the following line of code: window.location.replace(url); Howe ...

"The issue persists in Angular 5 - I am using ngOnInit to fetch my object from firestore, but surprisingly the view does not reflect any

After working with Angular 5 and Firestore, I encountered an interesting issue. When retrieving my document and checking it using console.log(this.assets) in ngOnInit(), everything seems fine. However, a strange thing happens during a page reload: if I qui ...

Angular2's Dynamic Forms

When attempting to incorporate FormsArray into my Project using ReactiveFormsModule, I encountered an error message stating: Cannot find control with unspecified name attribute. Is it possible to add FormsArray in template driven forms? Here is the code ...

How to efficiently eliminate multiple entries with SREM in ioredis?

I am curious about the proper syntax for removing multiple entries using the SREM command. When I try this: const myKey = "myKey"; const entriesToRemove: string[] = ... this.redisClient.srem(myKey, entriesToRemove); I end up with: ReplyError: ...

Experimenting with a file system library function using Jest and Typescript alongside a placeholder function

When attempting to test a library function that uses the fs module, I received assistance in this question on Stack Overflow. The feedback suggested avoiding mocks for better testing, an approach I agreed with @unional. I am now facing a similar challenge ...

Learn how to render a single element with multiple child elements within separate `<td>` tags in a table row using React

I'm just starting out with React and I have a code snippet that I'm using to render an HTML table in a component. Is there a more optimized way to achieve this? bodyItems = sorted.map((data) => [ data.employerName, data.sectors.map((sector ...

Deciphering the Mysteries of API Gateway Caching

It seems like a common pattern to enable an API Gateway to serve an Angular Webapp by pulling it from S3. The setup involves having the API gateway with a GET request set up at the / route to pull index.html from the appropriate location in the S3 bucket, ...

Encountering an issue when using npm to add a forked repository as a required package

While attempting to install my fork of a repository, I encountered the error message "Can't install github:<repo>: Missing package name." The original repository can be accessed here, but the specific section I am modifying in my fork is located ...

Should the input field only contain spaces, a validation error will be triggered by the user

I am currently working on an Angular form implementation that allows users to enter their phone numbers. I have integrated a custom directive called appPhoneExtMask for formatting the phone numbers and have also implemented Angular form validation for both ...

Can a Bootstrap 5 modal popup be shown in Angular by utilizing an ngIf statement?

The issue we are facing here is related to the conditional display of a modal using ngIf. The problem arises because initially, when the page loads, the modal element is not present in the DOM as it is set to false by default. Therefore, on the first click ...

Navigating back in an Async Function within Angular

I am encountering an issue while trying to incorporate an if else condition within my async function in Angular. To prevent the error, I am required to include a return statement in my async function. asyncFunction: (value) => { let getApplica ...

Issue encountered while retrieving the response, in case the node.js server sends the response with a delay

My aim is to upload an image and have the nodeJS server send the path of that image folder back as a response. Unfortunately, when I try sending the response after completing a task, nothing seems to be happening on the angular-side. Below is my componen ...

The confirm alert from Material UI is being obscured by the dialog

How can I ensure that a material ui dialog does not hide the alert behind it when confirming an action? Is there a way to adjust the z index of the alert so that it appears in front of the dialog? import Dialog from "@material-ui/core/Dialog"; i ...