Angular中RxJS订阅代码晚于组件加载执行的问题求助
解决Angular登录后权限代码晚于组件初始化执行的问题
核心问题是你在login函数中调用rolesByID时,没有等待其内部的异步请求完成就继续执行后续逻辑并返回了Observable,导致组件初始化时sessionStorage里还没有权限数据。
修复步骤:
重构
rolesByID函数,让它返回Observable而非内部subscribe
把原本在subscribe回调里的逻辑移到RxJS操作符中,让函数返回一个Observable,这样外部可以等待它完成。在
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
相关产品推荐
相关产品推荐

