You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何实时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:45:03