如何通过Angular Resolver实现数据加载完成后再渲染组件
你现在的逻辑不生效的核心是 Angular Resolver 的工作机制要求 resolve 方法必须返回 Observable、Promise 或者具体值,只有当返回的 Observable 完成、或 Promise 被 resolve 时,才会放行渲染目标组件。你当前的 resolve 方法返回 void,调用完 dispatch 就直接结束了,并不会等待内部的异步请求完成,所以组件会提前渲染。
以下是两种可直接落地的修改方案:
方案一:调整Service返回Observable(推荐)
1. 修改CategoriesService的dispatch方法
移除内部订阅逻辑,直接返回请求的Observable,数据存储逻辑保留在tap操作符中:
// CategoriesService 中修改dispatch方法 dispatch(): Observable<CategoryModel[]> { return this.httpService .getCategories(12) .pipe(tap((categories) => this.categories$.next(categories))); }
2. 修改Resolver返回Observable
让resolve方法直接返回dispatch返回的Observable,Resolver会自动订阅并等待请求完成:
@Injectable({ providedIn: 'root' }) export class ProductsCategoriesResolver implements Resolve<CategoryModel[]> { constructor(private categoriesService: CategoriesService) {} resolve(): Observable<CategoryModel[]> { return this.categoriesService.dispatch(); } }
这种方案不需要额外的监听逻辑,性能更好,也不需要额外管理订阅避免内存泄漏。
方案二:保留Service内部订阅逻辑
如果你不想修改现有dispatch的内部订阅逻辑,可以在Resolver中监听数据存储的Subject,直到拿到有效数据再放行:
@Injectable({ providedIn: 'root' }) export class ProductsCategoriesResolver implements Resolve<CategoryModel[]> { constructor(private categoriesService: CategoriesService) {} resolve(): Observable<CategoryModel[]> { // 先触发数据加载 this.categoriesService.dispatch(); // 监听categories$,直到拿到非false的有效数据后完成 return this.categoriesService.categories$.pipe( filter((val): val is CategoryModel[] => val !== false), take(1) // 只取第一次有效值,自动结束Observable ); } }
两种方案都可以实现仅在数据存储到CategoriesService后才渲染组件的需求,和Guard的拦截效果完全一致。
内容的提问来源于stack exchange,提问作者ashv9
相关产品推荐
相关产品推荐

