W1l*_*orm 3 observable rxjs typescript angular angular6
我创建了一个从服务器获取一些数据的服务,它们是制作我的组件所必需的,并且应该被调用一次,因为它会导致服务器上的巨大负载。当我在应用程序模块提供程序中使用服务时,它会一直等到获取所需的数据,并且它确实成功获取了它,因为我可以记录它,但是之后当我想在组件中获取它时,它返回未定义!
我试图通过从提供者中删除 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;
}
Run Code Online (Sandbox Code Playgroud)
将在 APP_INITIALIZATION 中使用的工厂:
export function adminProviderFactory(provider: UserService) {
return () => provider.getAdminInitInfo();
}
Run Code Online (Sandbox Code Playgroud)
AppModule 提供者:
providers: [
AuthGuardService,
AuthService,
{
provide: HTTP_INTERCEPTORS,
useClass: InterceptorService,
multi: true
},
UserService,
{
provide: APP_INITIALIZER,
useFactory: adminProviderFactory,
deps: [UserService],
multi: true
}
]
Run Code Online (Sandbox Code Playgroud)
我在组件中获得的数据日志:
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
Run Code Online (Sandbox Code Playgroud)
在这个过程之后,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;
}
Run Code Online (Sandbox Code Playgroud)
在一个组件中,例如:
ngOnInit() {
this.params = this.userService.getSomethingData();
}
Run Code Online (Sandbox Code Playgroud)
您要问的是一种满足组件要求的方法。这可以通过在路由中使用解析器来完成。
主要成分如下:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
解析器是在路由发生之前运行的代码段,它可以解析您需要的所有内容。当观察者完成时,解析器完成。
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
路由,即简单地使用解析器保护您的路由:
path: '',
component: MyLayout,
canActivate: [AuthGuard],
children: [
{ path: 'home', component: HomeComponent },
{ path: 'page1', component: Page1Component },
{ path: 'page', component: APage2Component },
],
resolve: { data: AuthenticatedAppResolver },
Run Code Online (Sandbox Code Playgroud)
您的组件和服务必须在providers您的模块部分注册。然后你就可以在任何受解析器保护的组件中自由使用 的getCachedData()方法ApplicationService。
请注意,解析器可能会被多次调用,但是,当我们缓存在服务中时,我们不会每次都询问它们。
更新
此方法一直有效,直到您拥有 1 个级别的子模块。如果它变得更复杂,或者您想要多个模块来使用这些数据,最好创建一个父模块并解析整个路由,然后在该路由模块中编写路由。例子:
const routes: Routes = [
{
path: 'login',
component: LoginComponent
},
{
path: '',
component: MyLayout,
canActivate: [AuthGuard],
children: [
{
path: 'dashboard',
children: [
{
path: '',
component: DashboardComponent
},
]
},
{
path: 'publisher',
loadChildren: './modules/publisher/publisher.module#PublisherModule'
}
],
resolve: {
data: AuthenticatedAppResolver
}
},
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1533 次 |
| 最近记录: |