Angular Resolver搭配NgRx Store Observable无响应问题排查
NgRx Store结合Resolver无法正常工作排查
我尝试了两种Resolver实现方式:
第一种:不使用Store的版本(可正常工作)
// @Injectable({ // providedIn: 'root', // }) // export class EmptyStateResolver implements Resolve<EmptyState> { // constructor() {} // resolve() { // const data = { // svg: 'test', // 原代码此处缺失逗号,已补全 // message: 'To see additional information, please select element from the list', // header: `Selected groups: `, // }; // return data; // } // }
第二种:结合NgRx Store Observable的版本(无法正常工作)
组件不显示,且无任何报错信息。调试时Chrome DevTools能在return data语句处停住且有对应值,说明逻辑已触发,但后续无任何反应。
代码实现:
constructor(protected readonly store$: Store) {} resolve(route: ActivatedRouteSnapshot): Observable<EmptyState> { return this.store$.select(selectors.getAllSelectedIDs).pipe( map((ids: ID[]) => { const data = { svg: '', message: !ids.length ? 'To see additional information, please select element from the list' : 'Use toolbar to perform desired actions for selected Items', header: `Selected groups: ${ids.length}`, }; return data; }) ); }
问题原因
Angular的Resolver机制要求返回的Observable完成后,才会继续加载目标组件。而NgRx Store的select()方法返回的是一个持续发射值的冷Observable,只要Store中的对应状态发生变化,它就会持续发射新值,永远不会主动完成。这就导致Resolver一直处于等待Observable完成的状态,组件永远无法被渲染。
解决方案
在Observable管道中添加take(1)操作符,只取第一个发射的值后就让Observable完成,这样Resolver就能正常拿到数据并继续流程:
resolve(route: ActivatedRouteSnapshot): Observable<EmptyState> { return this.store$.select(selectors.getAllSelectedIDs).pipe( take(1), // 添加此操作符 map((ids: ID[]) => { const data = { svg: '', message: !ids.length ? 'To see additional information, please select element from the list' : 'Use toolbar to perform desired actions for selected Items', header: `Selected groups: ${ids.length}`, }; return data; }) ); }
如果需要确保至少获取到一个值(比如状态可能还未初始化),可以改用first()操作符,它会等待第一个值发射后完成,若Observable永远不发射值则会抛出错误。
内容的提问来源于stack exchange,提问作者Bartek
相关产品推荐
相关产品推荐

