Angular - 在服务获取必要信息之前加载组件
Angular - a component loads before a service fetches necessary information
我目前正在为 observables 苦苦挣扎。我想我没有正确理解 rxjs 的主要概念。这就是我想要实现的目标。
在我的 Angular 应用程序中有一条通往 ProductShowComponent
的 /product/:slug
路线。要显示所有必要的信息,我首先需要使用 ProductsService
从 API 中获取所有产品。关键是,可能会在组件加载后获取产品(例如,当用户在 /product/:slug
上刷新页面时)。
我想做的是在 productsService
中实现一个 onReady
方法,在 ProductShowComponent
中订阅它,并在从 [=] 中获取信息后显示产品40=]。我认为如果 onReady
方法 returns 和 Observable
监视 productsService.ready
值的变化是可能的,但我不知道该怎么做或者是否可能根本。也许有更好的方法来做到这一点?有什么想法吗?
产品-show.component.ts
(...)
public ngOnInit(): void {
this.route.params.subscribe(params => {
this.productsService.onReady().subscribe(() => {
this.product = this.productsService.get(params['productSlug'], 'slug')
})
})
}
(...)
products.service.ts
(...)
constructor(
private appClient: AppClient
) {
this.fetchAll().subscribe((products: Product[]) => {
this.products = products
this.ready = true
})
}
(...)
public onReady(): Observable<any> {
if (!this.ready) {
// return an observable that watches for changes of value of this.ready
} else {
return Observable.of(null)
}
}
(...)
你的方向是正确的,但我想补充两点。你可以用其中任何一个来解决你的问题,但我认为两者都是有效的。
服务应通过可观察对象公开状态
在您的示例中,您的服务正在存储当前项目,然后公开该不可观察的状态。因此,例如,您可以...
产品-show.component.ts
public ngOnInit(): void {
this.route.params.subscribe(params => {
this.productsService.get(params['productSlug']).subscribe(product =>
this.product = product;
});
});
}
products.service.component.ts
constructor(
private appClient: AppClient
) {
this.products = this.fetchAll().publish();
this.productsSub = this.products.connect();
}
get(productId: string, idType: string) {
return this.products.map(products => {
return this.getProductFromProducts(products, productId, idType);
});
}
现在您真的不需要为 ready 标志而烦恼,因为您可以在构建服务后立即调用 get。
另一个优点是,如果某些原因导致您的可用产品设置发生变化,那么您的组件将自动更新(前提是您的服务已扩展为在发生变化时重新获取数据)。
为动态应用程序状态使用主题
现在假设您确实需要就绪标志。例如,您可能有几个组件显示一些 "data loading" 标志,直到加载所有初始应用程序数据(可能来自多个服务)。但是,出于示例目的,我们将只解决您最初的主题问题。因此,保留您的组件,我们可以将您的服务修改为...
products.service.component.ts
constructor(
private appClient: AppClient
) {
this.ready = new BehaviorSubject<boolean>(false);
this.fetchAll().subscribe((products: Product[]) => {
this.products = products
this.ready.next(true);
});
}
由于主题是可观察的,因此您不需要 onReady
您可以直接订阅 ready
。
我目前正在为 observables 苦苦挣扎。我想我没有正确理解 rxjs 的主要概念。这就是我想要实现的目标。
在我的 Angular 应用程序中有一条通往 ProductShowComponent
的 /product/:slug
路线。要显示所有必要的信息,我首先需要使用 ProductsService
从 API 中获取所有产品。关键是,可能会在组件加载后获取产品(例如,当用户在 /product/:slug
上刷新页面时)。
我想做的是在 productsService
中实现一个 onReady
方法,在 ProductShowComponent
中订阅它,并在从 [=] 中获取信息后显示产品40=]。我认为如果 onReady
方法 returns 和 Observable
监视 productsService.ready
值的变化是可能的,但我不知道该怎么做或者是否可能根本。也许有更好的方法来做到这一点?有什么想法吗?
产品-show.component.ts
(...)
public ngOnInit(): void {
this.route.params.subscribe(params => {
this.productsService.onReady().subscribe(() => {
this.product = this.productsService.get(params['productSlug'], 'slug')
})
})
}
(...)
products.service.ts
(...)
constructor(
private appClient: AppClient
) {
this.fetchAll().subscribe((products: Product[]) => {
this.products = products
this.ready = true
})
}
(...)
public onReady(): Observable<any> {
if (!this.ready) {
// return an observable that watches for changes of value of this.ready
} else {
return Observable.of(null)
}
}
(...)
你的方向是正确的,但我想补充两点。你可以用其中任何一个来解决你的问题,但我认为两者都是有效的。
服务应通过可观察对象公开状态
在您的示例中,您的服务正在存储当前项目,然后公开该不可观察的状态。因此,例如,您可以...
产品-show.component.ts
public ngOnInit(): void {
this.route.params.subscribe(params => {
this.productsService.get(params['productSlug']).subscribe(product =>
this.product = product;
});
});
}
products.service.component.ts
constructor(
private appClient: AppClient
) {
this.products = this.fetchAll().publish();
this.productsSub = this.products.connect();
}
get(productId: string, idType: string) {
return this.products.map(products => {
return this.getProductFromProducts(products, productId, idType);
});
}
现在您真的不需要为 ready 标志而烦恼,因为您可以在构建服务后立即调用 get。
另一个优点是,如果某些原因导致您的可用产品设置发生变化,那么您的组件将自动更新(前提是您的服务已扩展为在发生变化时重新获取数据)。
为动态应用程序状态使用主题
现在假设您确实需要就绪标志。例如,您可能有几个组件显示一些 "data loading" 标志,直到加载所有初始应用程序数据(可能来自多个服务)。但是,出于示例目的,我们将只解决您最初的主题问题。因此,保留您的组件,我们可以将您的服务修改为...
products.service.component.ts
constructor(
private appClient: AppClient
) {
this.ready = new BehaviorSubject<boolean>(false);
this.fetchAll().subscribe((products: Product[]) => {
this.products = products
this.ready.next(true);
});
}
由于主题是可观察的,因此您不需要 onReady
您可以直接订阅 ready
。