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

Angular中RxJS订阅代码晚于组件加载执行的问题求助

解决Angular登录后权限代码晚于组件初始化执行的问题

核心问题是你在login函数中调用rolesByID时,没有等待其内部的异步请求完成就继续执行后续逻辑并返回了Observable,导致组件初始化时sessionStorage里还没有权限数据。

修复步骤:

  1. 重构rolesByID函数,让它返回Observable而非内部subscribe
    把原本在subscribe回调里的逻辑移到RxJS操作符中,让函数返回一个Observable,这样外部可以等待它完成。

  2. 在login函数中等待rolesByID完成后再更新用户状态
    使用concatMap或mergeMap串联两个异步请求,确保权限数据写入sessionStorage后,再触发用户状态更新和组件初始化。


修改后的代码示例

1. 重构rolesByID函数

rolesByID(userID: any, token: any): Observable<void> {
  return this.userService.rolesByID(userID, token).pipe(
    tap((rol) => {
      // 设置用户角色ID
      sessionStorage.setItem("Rol", JSON.stringify(userID));
      // 用对象映射简化权限判断逻辑
      const permissionKeys: Record<string, string> = {
        "Alarmas": "Alarmas",
        "Clientes": "Clientes",
        "Establecimientos": "Establecimientos",
        "Estadisticas": "Estadisticas",
        "Perfiles": "Perfiles",
        "Sensores": "Sensores",
        "Usuarios": "Usuarios"
      };
      
      rol.forEach((element: any) => {
        const key = permissionKeys[element.funcion.nombre];
        if (key) {
          sessionStorage.setItem(key, JSON.stringify(element));
        }
      });
      
      console.log(sessionStorage.getItem("Usuarios"));
    }),
    // 转换为void类型的Observable,明确返回值类型
    map(() => void 0)
  );
}

2. 更新login函数的mergeMap逻辑

login(email: string, password: string): Observable<UserType> {
  this.isLoadingSubject.next(true);
  
  return this.http.post<Usuario>(`${Constants.urlBase}/auth/signin`, { email, password }).pipe(
    mergeMap((user: any) => {
      if (user) {
        this.usuario = user;
        
        // 等待rolesByID请求完成后,再处理用户状态
        return this.rolesByID(user.id, user.token).pipe(
          map(() => {
            // 强制设置西班牙语
            user.language = 'es';          
            // 保存用户到本地存储
            this.setAuthFromLocalStorage(user);
            // 更新当前用户Subject
            this.currentUserSubject.next(user);
            
            return user;
          })
        );
      } else {
        this.logout();
        return of(user);
      }
    }),
    catchError((err) => {
      console.error('err', err);
      return of(undefined);
    }),
    finalize(() => this.isLoadingSubject.next(false))
  );
}

额外说明

如果你的组件是通过路由导航加载的,建议配合**路由守卫(CanActivate)**使用:在守卫中等待login的Observable完成后,再允许进入组件,彻底确保权限数据已准备就绪。

内容的提问来源于stack exchange,提问作者Mikle Culaciati

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:55:20