我创建了一个服务,该服务从服务器获取一些数据,它们是制作我的组件所必需的,应该被调用一次,因为这会给服务器带来巨大的负担。当我在应用程序模块提供程序中使用服务时,它会等到获取所需数据后才成功获取它,因为我可以对其进行记录,但是此后,当我想要在组件中获取它时,它将返回未定义!
我试图通过从提供者中删除UserService来将服务的初始化次数减少到1,但这会导致错误。
获取信息的功能:
getAdminInitInfo(): Promise<any> {
var vm = this;
const promise = this.http.get<AdminInit>(baseUrl + '/panel/admin/initial/')
.toPromise()
.then(
response => {
vm.adminInitInfo = response;
console.log(response);
}
)
return promise;
}
将在APP_INITIALIZATION中使用的工厂:
export function adminProviderFactory(provider: UserService) {
return () => provider.getAdminInitInfo();
}
AppModule提供程序:
providers: [
AuthGuardService,
AuthService,
{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
},
UserService,
{
provide: APP_INITIALIZER,
useFactory: adminProviderFactory,
deps: [UserService],
multi: true
}
]
我在组件中获得的数据日志:
user.service.ts:23 service started
user.service.ts:23 service started
user.service.ts:70 {filters: {…}}
user.service.ts:78 undefined
overview.component.ts:19 undefined
在执行此过程之后,只要我需要使用此函数,就可以随时返回adminInitInfo:
getSomethingData() {
var data = {};
console.log(this.adminInitInfo);
if (!this.adminInitInfo) {
return undefined;
}
data['something'] = this.adminInitInfo.filters.something;
data['something2'] = this.adminInitInfo.filters.something2;
data['something3'] = this.adminInitInfo.filters.something3;
return data;
}
在诸如以下的组件中
ngOnInit() {
this.params = this.userService.getSomethingData();
}
答案 0 :(得分:2)
您要问的是一种满足组件要求的方法。这可以通过在路由中使用解析器来完成。
关键成分如下:
服务,其中包含您所需的信息(ApplicationData
是我的一类,其中包含有关应用程序的信息,例如用户名,版本等...,与以下信息无关此上下文):
@Injectable()
export class ApplicationService {
private cachedData: ApplicationData = null;
public constructor(/* place here your dependencies */) {
}
public initializeApplicationData(): Observable<ApplicationData> {
// return here the observable that builds your application data, like for example getting the user, and joining it with the version and tap it:
// if we already have the data, don't ask anything and simply return it
if (this.cachedData)
return of(this.cachedData);
return /* your service that builds the application data */.getApplicationData().pipe(
tap(x=> this.cachedData = x));
}
public getCachedData(): ApplicationData {
return this.cachedData;
}
}
解析器,它是在路由发生并解决所需所有内容之前运行的代码。观察者完成时,解析程序完成。
@Injectable()
export class AuthenticatedAppResolver implements Resolve<Observable<ApplicationData>> {
public constructor(private applicationService: ApplicationService) { }
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ApplicationData> {
return this.applicationService.initializeApplicationData();
}
}
路由,即只需使用解析器保护您的路由即可:
path: '',
component: MyLayout,
canActivate: [AuthGuard],
children: [
{ path: 'home', component: HomeComponent },
{ path: 'page1', component: Page1Component },
{ path: 'page', component: APage2Component },
],
resolve: { data: AuthenticatedAppResolver },
您的组件和服务必须在模块的providers
部分中进行注册。然后,您可以在解析器保护的任何组件中自由使用getCachedData()
的{{1}}方法。
请注意,解析程序可能会被调用多次,但是,由于我们在服务中进行缓存,因此我们不会每次都询问它们。
更新
直到您拥有1级子模块,此方法才有效。如果变得更加复杂,或者您希望多个模块使用这些数据,则最好创建一个父模块并解析整个路由,然后在该路由模块中写入路由。 示例:
ApplicationService
答案 1 :(得分:0)
我想您的方法太复杂了。而且,您永远不会返回response
的值。改为尝试这种方式:
getAdminInitInfo(): Promise<any> {
return this.http.get<AdminInit>(baseUrl + '/panel/admin/initial/')
.toPromise()
.then(
response => { return response.json(); }
);
}
response.json()
已经返回了诺言。
或更短:
getAdminInitInfo(): Promise<any> {
return this.http.get<AdminInit>(baseUrl + '/panel/admin/initial/')
.toPromise()
.then(
response => response.json()
);
}