服务在 APP_INITIALIZER 之后实例化了两次
Service instantiated twice after APP_INITIALIZER
问题是:我需要进行 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
正在重新实例化?
根据您在 application.service.ts
中添加 providedIn: root
的解释,这意味着它将被添加到根模块(即 Appmodule.ts)并再次添加到 Appmodule.ts
在您的 provider
数组中添加 ApplicationService
。
据此 Blog 表示
"There is now a new, recommended, way to register a provider, directly
inside the @Injectable() decorator, using the new providedIn
attribute. It accepts 'root' as a value or any module of your
application. When you use 'root', your injectable will be registered
as a singleton in the application, and you don’t need to add it to the
providers of the root module. Similarly, if you use providedIn:
UsersModule, the injectable is registered as a provider of the
UsersModule without adding it to the providers of the module."
正在创建要重新实例化的服务
编辑 1 :
另一件要检查的事情是,
1. 你如何调用这个服务我的意思是在开发模式或生产模式下,如果是开发模式那么服务将被调用两次
If you're running in development mode, it will run the function at
least twice. since in development mode it does a check, changes, then
rechecks to verify, where production mode only does the first check,
assuming you've done your quality assurance and resolved any values
the get changed post checking.
尝试在 Prod 模式下检查并验证它..
发现问题:这是因为路由器,需要作为注入到 ApplicationService 中的服务的依赖项。
参见示例:
https://stackblitz.com/edit/angular-xwyugy
当 Router 从 ApplicationService 中移除时,双重实例化就消失了。
不明白为什么,等待更好的答案批准。
这样做的原因是,一旦您将 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 ) {
}
}
我还遇到了一个问题,即我的服务被实例化了两次,从我在日志中看到的情况来看,一个构造函数是从 config.service.ts
文件调用的,第二个是从 config.service.js
调用的(注意扩展名差异).发生错误,我像这样导入了我的服务:
import { ConfigService } from '../config/config.service.js';
而不是:
import { ConfigService } from '../config/config.service';
将其更改为正确的导入解决了这个问题。
问题是:我需要进行 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
正在重新实例化?
根据您在 application.service.ts
中添加 providedIn: root
的解释,这意味着它将被添加到根模块(即 Appmodule.ts)并再次添加到 Appmodule.ts
在您的 provider
数组中添加 ApplicationService
。
据此 Blog 表示
"There is now a new, recommended, way to register a provider, directly inside the @Injectable() decorator, using the new providedIn attribute. It accepts 'root' as a value or any module of your application. When you use 'root', your injectable will be registered as a singleton in the application, and you don’t need to add it to the providers of the root module. Similarly, if you use providedIn: UsersModule, the injectable is registered as a provider of the UsersModule without adding it to the providers of the module."
正在创建要重新实例化的服务
编辑 1 : 另一件要检查的事情是, 1. 你如何调用这个服务我的意思是在开发模式或生产模式下,如果是开发模式那么服务将被调用两次
If you're running in development mode, it will run the function at least twice. since in development mode it does a check, changes, then rechecks to verify, where production mode only does the first check, assuming you've done your quality assurance and resolved any values the get changed post checking.
尝试在 Prod 模式下检查并验证它..
发现问题:这是因为路由器,需要作为注入到 ApplicationService 中的服务的依赖项。
参见示例: https://stackblitz.com/edit/angular-xwyugy
当 Router 从 ApplicationService 中移除时,双重实例化就消失了。
不明白为什么,等待更好的答案批准。
这样做的原因是,一旦您将 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 ) {
}
}
我还遇到了一个问题,即我的服务被实例化了两次,从我在日志中看到的情况来看,一个构造函数是从 config.service.ts
文件调用的,第二个是从 config.service.js
调用的(注意扩展名差异).发生错误,我像这样导入了我的服务:
import { ConfigService } from '../config/config.service.js';
而不是:
import { ConfigService } from '../config/config.service';
将其更改为正确的导入解决了这个问题。