解决由于 APP_INITIALIZER 引起的循环依赖
Solving cyclic dependency due to APP_INITIALIZER
我有一个加载 AngularFirestore
的服务 AuthenticationService
。该服务已在 RootComponent
中加载。 RootComponent
中的所有应用程序模块都是延迟加载的(它有主要的 router-outlet
)。现在有很多子模块也加载AngularFirestore
.
我必须确保 AuthenticationService
在加载组件和模块之前被初始化(异步的东西),所以我把它放在 APP_INITIALIZER
提供程序中。这导致 cyclic-dependency Cannot instantiate cyclic dependency! AngularFirestore
.
如果我不把它放在 APP_INITIALIZER
中,它可以工作,但应用程序运行时没有 AuthenticationService
被初始化。
有办法解决这个问题吗? (除了在所有组件中添加auth.initialize()
)
应用树:
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();
}
此致!
因此,在浏览了大量 github 评论和不相关的 SO 问题后,我想出了一个解决方案,我在 Github 评论中浏览了一个不相关的问题。
TLDR:通过为 AngularFirestore
或整个应用程序创建新服务来进行注入。我选择了后者。
理解问题:
据我了解,问题是因为我的 AuthenticationService
加载了 AngularFirestore
并使其成为依赖树的一部分。现在 AuthenticationService
和 AngularFirestore
的任何后续注入都会产生循环依赖,因为注入 AuthenticationService
会使 AngularFirestore
成为依赖树的一部分,并且当我注入 AngularFirestore
之后它创建了两次 AngularFirestore
注入。因此错误。我可能完全错了,但我认为这就是问题所在。
解法:
为 AngularFirestore
导入创建服务。我认为,这会将它从依赖树中移出并将其作为服务注入,使其可以用于任何后续注入 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,
]
},
对于我的情况,我必须创建一个服务来加载 RemoteConfigService
和 AuthenticationService
,因为它们必须一个接一个地初始化。
此致!
我有一个加载 AngularFirestore
的服务 AuthenticationService
。该服务已在 RootComponent
中加载。 RootComponent
中的所有应用程序模块都是延迟加载的(它有主要的 router-outlet
)。现在有很多子模块也加载AngularFirestore
.
我必须确保 AuthenticationService
在加载组件和模块之前被初始化(异步的东西),所以我把它放在 APP_INITIALIZER
提供程序中。这导致 cyclic-dependency Cannot instantiate cyclic dependency! AngularFirestore
.
如果我不把它放在 APP_INITIALIZER
中,它可以工作,但应用程序运行时没有 AuthenticationService
被初始化。
有办法解决这个问题吗? (除了在所有组件中添加auth.initialize()
)
应用树:
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();
}
此致!
因此,在浏览了大量 github 评论和不相关的 SO 问题后,我想出了一个解决方案,我在 Github 评论中浏览了一个不相关的问题。
TLDR:通过为 AngularFirestore
或整个应用程序创建新服务来进行注入。我选择了后者。
理解问题:
据我了解,问题是因为我的 AuthenticationService
加载了 AngularFirestore
并使其成为依赖树的一部分。现在 AuthenticationService
和 AngularFirestore
的任何后续注入都会产生循环依赖,因为注入 AuthenticationService
会使 AngularFirestore
成为依赖树的一部分,并且当我注入 AngularFirestore
之后它创建了两次 AngularFirestore
注入。因此错误。我可能完全错了,但我认为这就是问题所在。
解法:
为 AngularFirestore
导入创建服务。我认为,这会将它从依赖树中移出并将其作为服务注入,使其可以用于任何后续注入 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,
]
},
对于我的情况,我必须创建一个服务来加载 RemoteConfigService
和 AuthenticationService
,因为它们必须一个接一个地初始化。
此致!