Angular ComponentStore updater中state始终为undefined问题排查
问题描述
我定义了继承自ComponentStore<SceneGraphState>的SceneGraphStore:
@Injectable({ providedIn: 'root', }) export class SceneGraphStore extends ComponentStore<SceneGraphState> { ... }
现在遇到的问题是:updateAxes这个updater方法里的state始终为undefined。虽然我已经通过loadSceneGraph effect正确加载并初始化了状态(日志显示state已经完成初始化,且changes参数能获取到后端返回的有效数据),但执行更新操作时store的状态是空的。
loadSceneGraph effect代码如下:
export const loadSceneGraph = (store: SceneGraphStore) => (equipmentNumber$: Observable<void>) => ...
这个effect在组件的ngOnInit中调用,组件内的日志也显示sceneGraph已经成功初始化:
public ngOnInit() { this.sceneGraphStore.loadSceneGraph(); ... }
updateAxes会在后端(Redis)推送实时设备数据时触发,我猜测可能是竞态条件导致的这个问题。
可能的解决思路
1. 让updateAxes等待状态就绪
在updateAxes触发前,先确认状态已经初始化完成。可以借助ComponentStore的select方法监听状态就绪状态,再执行更新:
// 在Store中定义状态就绪的流 readonly isStateReady$ = this.select(state => !!state); // 封装带状态校验的更新逻辑 readonly updateAxesOnReady = this.effect((changes$: Observable<YourChangeType>) => { return changes$.pipe( withLatestFrom(this.isStateReady$), filter(([_, isReady]) => isReady), map(([changes]) => changes), tap(changes => this.updateAxes(changes)) ); });
2. 检查loadSceneGraph的状态初始化逻辑
确认loadSceneGraph中是用setState来初始化状态,避免错误地使用其他方式覆盖或未正确写入状态:
readonly loadSceneGraph = this.effect((equipmentNumber$: Observable<void>) => { return equipmentNumber$.pipe( switchMap(() => yourApiFetchMethod()), tap(sceneGraphData => this.setState({ ...sceneGraphData })) // 确保用setState完成初始化 ); });
3. 调整Redis推送的订阅时机
如果Redis推送的订阅在状态初始化前就已建立,可能导致推送事件先于状态到达。可以等状态初始化完成后再订阅推送:
public ngOnInit() { this.sceneGraphStore.loadSceneGraph().pipe( switchMap(() => this.redisPushService.subscribeToAxesUpdates()) ).subscribe(changes => { this.sceneGraphStore.updateAxes(changes); }); }
4. 给updateAxes加兜底逻辑
在updateAxes中增加状态存在性校验,避免undefined导致的异常,同时确保正确合并现有状态与新数据:
readonly updateAxes = this.updater((state, changes: AxesChanges) => { if (!state) return state; // 状态未就绪时直接返回,避免报错 return { ...state, axes: { ...state.axes, ...changes } // 正确合并原有轴数据与新数据 }; });
内容的提问来源于stack exchange,提问作者Son Hai Vu
相关产品推荐
相关产品推荐

