如何在Angular的subscribe()中获取API返回值并存储到本地?
问题分析
你的核心问题是认证服务的login方法修改了Observable的数据流,导致组件subscribe时无法拿到完整的API响应数据:
在authentication.service.ts中,你先用map((data: any) => data.token)把API返回的完整对象转换成了token字符串,接着用switchMap返回Preferences.set的Observable。最终组件subscribe时拿到的是Preferences.set的执行结果,而非原始的API响应,自然会出现res.auth为undefined的错误。
解决方案
提供两种可行的修改方案,根据你的需求选择:
方案一:在服务中完成所有本地存储(推荐)
直接在服务里处理token和用户信息的存储,同时返回原始API数据,让组件只负责页面跳转逻辑:
修改authentication.service.ts:
import { forkJoin } from 'rxjs'; // ...其他导入 login(credentials: { email: any, password: any }): Observable<any> { return this.http.post('https://mysite.test/api/login', credentials) .pipe( switchMap(data => { // 并行执行所有存储操作 return forkJoin([ from(Preferences.set({ key: 'token', value: data.token })), from(Preferences.set({ key: 'authName', value: data.auth.name })), from(Preferences.set({ key: 'authUsername', value: data.auth.username })) ]).pipe( // 存储完成后返回原始API数据 map(() => data) ); }), tap(() => { this.isAuthenticated.next(true); }) ); }
对应的login.page.ts可以简化:
async login() { const loading = await this.loadingController.create(); await loading.present(); this.authService.login(this.myForm.value) .subscribe( async () => { await loading.dismiss(); this.menu.enable(true); this.router.navigateByUrl('/tabs/home', { replaceUrl: true }); }, async (res) => { await loading.dismiss(); const alert = await this.alertController.create({ header: 'Login Failed', message: res.error.message, buttons: ['OK'], }); await alert.present(); } ); }
方案二:在组件中处理用户信息存储
如果坚持要在组件里处理用户信息存储,只需修改服务,确保它返回完整的API响应数据:
修改authentication.service.ts:
login(credentials: { email: any, password: any }): Observable<any> { return this.http.post('https://mysite.test/api/login', credentials) .pipe( tap(data => { // 仅存储token,不修改数据流 Preferences.set({ key: 'token', value: data.token }); this.isAuthenticated.next(true); }) ); }
此时login.page.ts的原有代码即可正常工作,因为subscribe拿到的是完整的API响应对象,res.auth不再是undefined。
内容的提问来源于stack exchange,提问作者timgavin
相关产品推荐
相关产品推荐

