2

I have a service AuthenticationService that loads AngularFirestore. The service is loaded in RootComponent. All app modules are lazy-loaded in RootComponent (it has the main router-outlet). Now there are many sub-modules that also load AngularFirestore.

I have to ensure that AuthenticationService is initialized (async stuff) before the components and modules are loaded up, so I have put it in APP_INITIALIZER provider. This causes cyclic-dependency Cannot instantiate cyclic dependency! AngularFirestore.

If I don't put it in APP_INITIALIZER it works but the app runs without AuthenticationService being initialized.

Is there a way around this? (besides adding auth.initialize() in all components)

App tree:

AppComponent -> RootComponent(AuthenticationService) -> All Submodules(AuthenticationService, AngularFirestore)
// constructor of AuthenticationService
constructor(
    private auth : AngularFireAuth,
    private remoteconfig : AngularFireRemoteConfig,
    private keepalive: Keepalive,
    private idle: Idle, 
    private toast : ToastService,
    private router : Router,
    private fs : AngularFirestore,
    private http : HttpClient,
)
// providers in app.module.ts
{
  provide: APP_INITIALIZER,
  multi: true,
  useFactory: authFactory,
  deps: [
    AuthenticationService
  ]
}
// Factory for APP_INITIALIZER
export function authFactory(
  auth : AuthenticationService
) {
  return () : Promise<any> => auth.initialize();
}

Regards!

2
  • Didn't check your use-case in detail, but this usually happens because of the HTTP interceptors. See this issue. Commented Sep 12, 2020 at 19:49
  • @LazarLjubenović unfortunately i am not using any HTTP interceptors. Thanks for your input though! Commented Sep 12, 2020 at 19:53

1 Answer 1

1

So after going through a plethora of github comments and unrelated SO questions I came up with a solution that I skimmed through for an unrelated issue in Github comments.

TLDR: Make injection by creating a new service for AngularFirestore just for AuthenticationService or for the whole app. I went with the latter.

Understanding the problem:

From what I understand, the issue is because my AuthenticationService loads AngularFirestore and makes it part of its dependency tree. Now any subsequent injection of AuthenticationService and AngularFirestore makes a cyclic dependency, because injecting AuthenticationService makes AngularFirestore part of the dependency tree, and when I inject AngularFirestore after that it creates two injections of AngularFirestore. Hence the error. I may be completely wrong, but I think this was the issue.

Solution:

Create a service for AngularFirestore import. This, I think, moves it out of the dependency tree and injects it as a service making it OK for any subsequent injections of AngularFirestore safe.

// appfirestoreservice.ts
import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';

@Injectable({
  providedIn: 'root'
})
export class AppFirestoreService {
  
  public fs : AngularFirestore;
  public readonly collection = this._fs.collection;
  public readonly doc = this._fs.doc;
  public readonly createId = this._fs.createId;

  constructor(
    private _fs : AngularFirestore,
  ) {
    this.fs = _fs;
  }
}
// App Initializer in AppModule
{
  provide: APP_INITIALIZER,
  multi: true,
  useFactory: initFactory,
  deps: [
    AppServiceInitializerService,
    RemoteConfigService,
    AuthenticationService,
  ]
},

For my case I had to create a service just to load RemoteConfigService and AuthenticationService because they have to be initialized one after the other.

Regards!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.