Angular Route Resolver如何返回多份关联数据?
问题描述
我定义了一个路由组件,初始化时需要两份不同的数据。当前路由配置了SessionResolver,可成功获取Session数据并传递给组件。现在希望修改该解析器,先获取Session,再利用Session中的templateId调用服务获取Template数据,同时将Session和Template都返回给组件。目前使用switchMap链式调用只能返回Template,不清楚应返回何种类型,以及如何正确实现返回两者的逻辑。
路由配置代码
{ path: "session/:sessionId", component: CaptureComponent, resolve:{ session:SessionResolver }, data: { title: "Capture Session" } }
当前解析器代码(仅返回Session)
@Injectable() export class SessionResolver implements Resolve<Session> { constructor(private sessionService: SessionService) {} resolve(route: ActivatedRouteSnapshot): Observable<Session> { const sessionId:number = route.params['sessionId']; return this.sessionService.getSession(sessionId); } }
修改后的链式调用代码(仅返回Template)
@Injectable() export class SessionResolver implements Resolve<Template> { constructor(private sessionService: SessionService) {} resolve(route: ActivatedRouteSnapshot): Observable<Template> { const sessionId:number = route.params['sessionId']; return this.sessionService.getSession(sessionId) .pipe( switchMap(session => { const templateId = session.templateId!; return this.sessionService.getTemplate(templateId); }) ); } }
疑问
- 解析器应返回什么类型才能同时包含两份数据?
- 是否需要定义自定义类型,以及如何获取两次调用的结果并返回?
解决方案
1. 解析器返回类型的选择
你需要一个能同时容纳Session和Template的类型——要么自定义一个接口,要么直接用匿名对象类型。Angular的Resolve接口对泛型没有限制,只要是能包裹两份数据的类型都可以。
2. 具体实现方案
方案一:自定义类型(类型安全,推荐)
先定义一个专门的接口来组合两份数据:
export interface SessionWithTemplate { session: Session; template: Template; }
然后修改解析器,在switchMap里拿到session后,调用获取template的接口,再用map把两者打包成自定义类型的对象返回:
@Injectable() export class SessionResolver implements Resolve<SessionWithTemplate> { constructor(private sessionService: SessionService) {} resolve(route: ActivatedRouteSnapshot): Observable<SessionWithTemplate> { const sessionId = +route.params['sessionId']; return this.sessionService.getSession(sessionId) .pipe( switchMap(session => { const templateId = session.templateId!; return this.sessionService.getTemplate(templateId).pipe( map(template => ({ session, template })) ); }) ); } }
方案二:匿名对象(快速实现,无需额外定义类型)
如果不想新增接口,直接返回包含两个属性的匿名对象即可,此时Resolve的泛型写成{ session: Session; template: Template }:
@Injectable() export class SessionResolver implements Resolve<{ session: Session; template: Template }> { constructor(private sessionService: SessionService) {} resolve(route: ActivatedRouteSnapshot): Observable<{ session: Session; template: Template }> { const sessionId = +route.params['sessionId']; return this.sessionService.getSession(sessionId) .pipe( switchMap(session => { const templateId = session.templateId!; return this.sessionService.getTemplate(templateId).pipe( map(template => ({ session, template })) ); }) ); } }
组件中如何获取数据
修改完解析器后,在CaptureComponent里通过路由快照的data属性就能拿到两份数据:
import { ActivatedRoute } from '@angular/router'; @Component({/* 组件配置 */}) export class CaptureComponent { constructor(private route: ActivatedRoute) { const resolverData = this.route.snapshot.data['session']; const session = resolverData.session; const template = resolverData.template; // 后续即可使用这两个数据初始化组件 } }
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

