Home > Blockchain >  "No provider for service" in APP_INITIALIZER factory
"No provider for service" in APP_INITIALIZER factory

Time:04-06

In my backend, I have some API resources which return some configuration information to the frontend. Since I don't want to call them for each resource I show, I want to do it upfront.

From what I've seen, APP_INITIALIZER looks promising, so I tried it: https://stackblitz.com/edit/angular-ivy-4yfvtk?file=src/link.service.ts But it is not able to inject the LinkService.

I added the service with deps to the AppModule. I am not quite sure what the issue is. Furthermore, I've checked other topics, but as far as I can tell it is the same.

What am I missing?

CodePudding user response:

There are quite a few adjustments that you need to make in order for this to work:

  1. There is no provider for the LinkService, you should either provide it in root using @Injectable({providedIn: 'root'}) or adding it in the providers array of the AppModule
  2. You need to import HttpClientModule in your app module, otherwise there is no provider for HttpClient service.
  3. The LinkService instance will be provided as the first parameter of the topmost function that you use as your factory method. It should look like this:
export function initLinkService(service: LinkService) {
  return () =>
    new Promise((resolve, reject) => {
      console.log('before init', service);
      service.init();
      console.log('after init', service);
      resolve(null);
    });
}

Then the AppModule registration changes to this:

@NgModule({
  imports: [BrowserModule, FormsModule, HttpClientModule],
  declarations: [AppComponent, HelloComponent],
  bootstrap: [AppComponent],
  providers: [
    LinkService,
    {
      provide: APP_INITIALIZER, 
      useFactory: initLinkService,
      deps: [LinkService],
      multi: true,
    },
  ],
})

CodePudding user response:

You got it wrong little bit.

First, your init funtion must return a function that produces a promise

export function initLinkService(service: LinkService) {
  return () =>
    new Promise((resolve, reject) => {
      console.log('before init', service);
      service.init();
      console.log('after init', service);
      resolve(null);
    });
}

Then you have to actually provide LinkService by including it into providers section. Moreover, you have to import HttpClientModule. Then you provide init method directly

@NgModule({
  imports: [BrowserModule, FormsModule, HttpClientModule], //import
  declarations: [AppComponent, HelloComponent],
  bootstrap: [AppComponent],
  providers: [
    LinkService, // required provider
    {
      provide: APP_INITIALIZER, 
      useFactory: initLinkService, //pass factory method directly
      deps: [LinkService],
      multi: true,
    },
  ],

Now, it will work https://stackblitz.com/edit/angular-ivy-4yfvtk?file=src/app/app.module.ts

  • Related