为何实时Observable登出后仍触发?如何阻止该异常执行行为?
问题根源
你用AngularFire的snapshotChanges()返回的是长连接可观察对象,默认会一直保持订阅状态持续推送数据,除非主动终止订阅。
当前Effect里的switchMap只有在新的loggedIn action触发时,才会取消上一次的旧订阅;但你触发登出操作时,没有任何逻辑终止当前活跃的DB监听流,因此登出后这个流依旧存活,哪怕你没有修改DB数据,AngularFire也可能因为登出后权限变更、连接状态变化等原因推送新值(比如无权限读取文档时返回null),触发userLoaded action把已经被reducer清空的用户状态重新覆盖,导致登出看起来失效。
你注释的first()操作符会在取到第一次DB返回值后直接结束流,所以不会有后续推送自然不会触发登出后的问题,但也直接砍掉了实时更新的能力,不符合需求。
修复方案
用takeUntil操作符监听logout action,一旦登出操作触发就主动终止当前的DB监听流,这是NgRx Effect中处理长连接流的标准方案,既保留实时更新能力,也能在登出后停止推送。
修改后的Effect代码如下:
// 需要先导入rxjs的takeUntil操作符 import { takeUntil } from 'rxjs'; getDbUser = createEffect(() => this.actions$.pipe( ofType(userActions.loggedIn), switchMap(({ user: { uid } }) => this.databaseService.getUser(uid).pipe( map((dbUser) => userActions.userLoaded({ dbUser })), // 新增行:监听到logout action时立即终止当前DB监听流 takeUntil(this.actions$.pipe(ofType(userActions.logout))) ) ) ) );
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

