Angular14中RxJS等待接口响应后执行后续代码的问题
解决方案:利用RxJS异步流等待服务变量更新
你的问题根源在于HTTP请求是异步操作,组件调用getAuthenticatedUserProfile()后会立即执行后续代码,此时API还未返回数据,服务中的auth变量仍为初始值。浏览器控制台展开对象时会读取最新状态,所以会出现"初始显示null,展开后有值"的现象。
下面提供两种不依赖localStorage的RxJS解决方案:
方案一:让服务返回Observable,组件订阅后执行后续逻辑
这种方式最直接,将HTTP请求的Observable返回给组件,由组件在请求完成的回调中处理后续操作。
修改服务代码
移除服务内的subscribe,改用tap操作符处理变量更新和store派发,最终返回Observable:
getAuthenticatedUserProfile(): Observable<any> { return this._http .get(`${environment.apiUrl}/user/state-profile`, { headers: GlobalHeaders.HTTP_HEADERS, observe: 'response', responseType: 'json', withCredentials: true }) .pipe( tap((data: any) => { let auth = data.body?.data; let payload = { userId: auth?.user_id, userName: auth?.user_name, userFullName: auth?.name, userEmail: auth?.email, roleName: auth?.role, profileId: auth?.profile_id, profileName: auth?.profile_name, userZone: auth?.zones, userState: auth?.states, userDistrict: auth?.districts, userAccessMenu: auth?.user_menus, allMenu: auth?.all_menus, isOtpRequired: auth?.require_otp, isLoggedIn: true }; this.auth = payload; this._store.dispatch(new UpdateAuthAction(payload)); }) ); }
修改组件代码
订阅服务返回的Observable,在next回调中执行路由等后续逻辑:
constructor(private renderer: Renderer2, private _authService: AuthService, private router: Router) {} ngOnInit(): void { let configItems = JSON.parse(localStorage.getItem('appConfig') || '{}'); this.appName = configItems.appName || 'Demo App'; this.otpForm = new UntypedFormGroup({ otp: new UntypedFormControl(null,[ Validators.required, Validators.pattern(/^\d{1,6}$/)]) }); // 订阅请求结果,等待数据返回后执行后续代码 this._authService.getAuthenticatedUserProfile().subscribe({ next: () => { console.log(this._authService.auth); // 此时auth已更新 const auth = this._authService.auth; if (!auth.isLoggedIn || !auth.isOtpRequired) { this.router.navigate(['/dashboard']); } }, error: (err) => { // 处理请求失败的情况,比如跳转登录页 console.error('获取用户信息失败', err); this.router.navigate(['/login']); } }); }
方案二:用BehaviorSubject发布状态更新(适合多组件监听场景)
如果你的应用中有多个组件需要监听auth状态变化,可以在服务中使用BehaviorSubject来发布状态,组件订阅这个Subject获取最新值。
修改服务代码
添加BehaviorSubject用于发布auth状态:
import { BehaviorSubject, Observable } from 'rxjs'; // 定义BehaviorSubject,初始值为null private authSubject = new BehaviorSubject<any>(null); // 对外暴露可观察对象,防止外部直接修改Subject public auth$ = this.authSubject.asObservable(); getAuthenticatedUserProfile() { return this._http .get(`${environment.apiUrl}/user/state-profile`, { headers: GlobalHeaders.HTTP_HEADERS, observe: 'response', responseType: 'json', withCredentials: true }) .subscribe({ next: (data: any) => { let auth = data.body?.data; let payload = { userId: auth?.user_id, userName: auth?.user_name, userFullName: auth?.name, userEmail: auth?.email, roleName: auth?.role, profileId: auth?.profile_id, profileName: auth?.profile_name, userZone: auth?.zones, userState: auth?.states, userDistrict: auth?.districts, userAccessMenu: auth?.user_menus, allMenu: auth?.all_menus, isOtpRequired: auth?.require_otp, isLoggedIn: true }; this.auth = payload; this.authSubject.next(payload); // 发布状态更新 this._store.dispatch(new UpdateAuthAction(payload)); }, error: (err) => { this.authSubject.error(err); // 传递错误信息 } }); }
修改组件代码
订阅服务的auth$ Observable,等待状态更新:
constructor(private renderer: Renderer2, private _authService: AuthService, private router: Router) {} ngOnInit(): void { let configItems = JSON.parse(localStorage.getItem('appConfig') || '{}'); this.appName = configItems.appName || 'Demo App'; this.otpForm = new UntypedFormGroup({ otp: new UntypedFormControl(null,[ Validators.required, Validators.pattern(/^\d{1,6}$/)]) }); // 触发请求 this._authService.getAuthenticatedUserProfile(); // 订阅auth状态变化 this._authService.auth$.subscribe({ next: (auth) => { if (auth) { // 确保auth已完成更新 console.log(auth); if (!auth.isLoggedIn || !auth.isOtpRequired) { this.router.navigate(['/dashboard']); } } }, error: (err) => { console.error('获取用户信息失败', err); this.router.navigate(['/login']); } }); }
内容的提问来源于stack exchange,提问作者Nirjhar Mistry
相关产品推荐
相关产品推荐

