目前,组件在数据加载之前显示(通过解析器),我将改变它。
我想要Guard之类的东西。→仅在数据存储时呈现。
我有三个文件:http。服务类别。服务和解析器。
http。服务只有HTTP调用类别。服务有方法"调度"。它具有获取数据并订阅它的整个逻辑。
我的解析器:
@Injectable({ providedIn: 'root' })
export class ProductsCategoriesResolver implements Resolve<any> {
constructor(private categoriesService: CategoriesService) {}
resolve(): void {
this.categoriesService.dispatch();
}
}
分类服务
@Injectable({ providedIn: 'root' })
export class CategoriesService implements OnDestroy {
categories$: BehaviorSubject<CategoryModel[] | false> = new BehaviorSubject(false);
categoryTitle$ = new BehaviorSubject(null);
private subscriptions = new Subscription();
constructor(private httpService: HttpService) {}
dispatch(): void {
this.subscriptions.add(
this.httpService
.getCategories(12)
.pipe(tap((categores) => this.categories$.next(categores)))
.subscribe(),
);
}
ngOnDestroy(): void {
this.subscriptions.unsubscribe();
}
}
http服务@Injectable({
providedIn: 'root',
})
export class HttpService {
constructor(private httpClient: HttpClient) {}
getCategories(limit: number): Observable<CategoryModel[]> {
const params: HttpParams = new HttpParams().append('limit', limit.toString());
return this.httpClient.get<ApiResponse<CategoryModel[]>>(`api/public/categories`, { params }).pipe(
map((response) => response.data),
map((categories) => {
return categories.map((category) => {
category.image = {
url: `/assets/images/products/product_${Math.floor(Math.random() * 4) + 1}.png`,
};
return category;
});
}),
);
}
}
路线:
const routes: Routes = [
{
path: '',
redirectTo: 'page/1',
pathMatch: 'full',
},
{
path: 'page/:pageNumber',
component: ProductsComponent,
resolve: {
products: ProductsCategoriesResolver,
},
},
您的设置实际上是您想要的行为所需要的唯一东西。解析器旨在延迟导航,直到为路由定义的所有解析器都返回结果(无论是同步的还是异步的)。你的解析器不返回任何东西,所以你的导航会立即发生,而从服务中获取数据只会在后台作为副作用发生。
你似乎也混淆了很多好的技术,因为它们并不是真的要一起工作(比如你在categories-service中的显式订阅管理)。这不会伤害到你,但是当请求结束时,通过Angular HttpClientModule的HttpClient
的请求就会完成,而你的服务是在应用的root
注入器中提供的,这意味着OnDestroy实际上永远不会被调用(直到用户关闭网站)。
你可以这样修改你的解析器:
@Injectable({ providedIn: 'root' })
export class ProductsCategoriesResolver implements Resolve<Observable<CategoryModel[]>> {
constructor(private categoriesService: CategoriesService) {}
resolve(): Observable<CategoryModel[]> {
this.categoriesService.dispatch();
return this.categoriesService.categories$.pipe(
filter(categories => !!categories),
take(1)
);
}
}
这意味着解析器只会完成,导航只会发生,一旦类别列表已被获取至少一次(和行为主题的值已从false
更改为CategoryModel
列表)。
做注意这意味着下一个请求的导航将立即发生,因为BehaviorSubject仍然保存上一个请求的值,所以需要做更多的工作,您可能需要考虑进一步更改实现。
看一下Resolve的官方文档,因为它有更多的内容(你可以访问路由快照中的数据,如果你只把它用于这个目的,就会使BehaviorSubject过时)。