问题是:我需要进行http调用并存储生成动态路由所需的对象。因此,我正在利用APP_INITIALIZER。
// app.module.ts
import { ApplicationService } from './application.service';
providers: [
ApplicationService,
{
provide: APP_INITIALIZER, useFactory: appServiceFactory, deps:
[Injector, ApplicationService], multi: true
},
],
function appServiceFactory(injector: Injector, appService: ApplicationService): Function {
return () => {
return appService.loadApplication().then((app: Application) => {
/custom logic
});
});
};
}
// application.service.ts
@Injectable({
providedIn: 'root'
})
// navigation.component.ts
import { ApplicationService } from './application.service';
export class NavigationComponent implements OnInit {
constructor(private _applicationService: ApplicationService) {
}
}
但是在navigation.component内部,applicationservice再次被初始化。我敢肯定,因为如果我记录或放置调试器语句,则该服务的Construct()方法将被调用两次。
为什么要重新实例化带有providedIn: root
的服务为单例?
答案 0 :(得分:3)
这样做的原因是,一旦将Router
包含在APP_INITIALIZER
工厂的依赖项中,您就会得到循环依赖项(https://github.com/angular/angular/blob/4c2ce4e8ba4c5ac5ce8754d67bc6603eaad4564a/packages/router/src/router_module.ts#L61-L64)。
ApplicationService
|
TestService
|
Router
|
ApplicationRef
|
ApplicationInitStatus
|
APP_INITIALIZER
|
ApplicationService
要解决此问题,您可以延迟获取路由器:
export class TestService {
get router() {
return this.injector.get(Router)
}
constructor(private _http: HttpClient, private injector: Injector ) {
}
}
答案 1 :(得分:1)
根据您的解释,即您在providedIn: root
中添加了application.service.ts
,这意味着它将被添加到根模块(即Appmodule.ts)中,并再次添加到Appmodule.ts
中在provider
数组中,您要添加ApplicationService
。
从此Blog开始,其状态
“现在有一种推荐的新方式可以直接注册提供商 在@Injectable()装饰器中,使用新的providerIn 属性。它接受“根”作为值或您的任何模块 应用。当您使用“ root”时,您的注射剂将被注册 作为应用程序中的单例,您无需将其添加到 根模块的提供者。同样,如果使用providerIn: UsersModule,注射剂已注册为 UsersModule,而无需将其添加到模块的提供程序中。”
这正在创建要重新实例化的服务
编辑1: 另一件事要检查的是, 1.在开发模式或生产模式下,您如何称呼此服务,如果是开发模式,则该服务将被调用两次
如果您在开发模式下运行,它将在以下位置运行该功能 至少两次。因为在开发模式下会进行检查,更改,然后 重新检查以验证,其中生产模式仅进行第一次检查, 假设您已经完成了质量保证并解决了所有价值 获取更改后的检查。
尝试在产品模式下检查并验证。.
答案 2 :(得分:0)
发现了问题:这是由于路由器,ApplicationApplication中注入的服务需要将其作为依赖项。
请参阅示例: https://stackblitz.com/edit/angular-xwyugy
将Router从ApplicationService中删除后,双重实例化消失了。
不明白为什么,所以我将等待更好的批准答案。
答案 3 :(得分:0)
我还面临一个问题,即我的服务被实例化了两次,并且从日志中看到的情况来看,从config.service.ts
文件中调用了一个构造函数,而从config.service.js
文件中调用了一个构造函数(请注意扩展名的区别)。发生这样的错误,我是这样导入服务的:
import { ConfigService } from '../config/config.service.js';
代替:
import { ConfigService } from '../config/config.service';
将其更改为正确的导入即可解决此问题。