Angular5登录跳转后token仍为空,需刷新才生效的问题排查
核心问题1:GlobalHttp服务的headers是静态初始化的
你的global-http.service里,token和_headers是在**服务实例化时(应用启动时)**就初始化的。当你登录后更新了localStorage里的token,但GlobalHttp服务里的token变量和_headers并没有同步更新——它们还是应用启动时的null值。只有刷新页面时,服务会重新实例化,才会从localStorage读取新的token。
核心问题2:Login函数的Observable处理错误
你的login函数声明返回Observable<UserModel>,但实际返回的是Subscription(因为调用了.subscribe()),这不仅类型不匹配,而且内部的return Observable.of(data.user)完全无效——subscribe回调里的return不会作为函数的返回值。
分步修复方案
1. 修复Login函数的Observable逻辑
用pipe+tap+map替代直接subscribe,保持返回Observable类型,同时正确处理登录后的token存储和路由跳转:
login(username: string, password: string): Observable<UserModel> { return this.globalHttp.post('login', {username,password}).pipe( // 用tap处理副作用(存token、跳转路由) tap(data => { const token = data.token; // 注意你原代码写的是token.data,需匹配实际接口返回格式 this.setToken(token); this.router.navigateByUrl("/profiles-list"); }), // 用map把响应转换为UserModel返回 map(data => data.user) ); }
2. 让GlobalHttp服务动态获取token
不要在类初始化时创建静态headers,而是每次请求时动态从localStorage读取最新token,确保请求用的是当前有效的token:
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class GlobalHttpService { private API_URL = '你的API前缀地址'; // 比如'http://localhost:8000/api/' constructor(private http: HttpClient) {} get(url: string, data?: any): Observable<any> { // 每次请求时最新获取token const token = localStorage.getItem('token') || null; // 动态创建headers const headers = new HttpHeaders() .set('Content-Type', 'application/json') .set('Authorization', token ? `Bearer ${token}` : ''); // 处理get请求的参数(如果有的话) let params = new HttpParams(); if (data) { Object.keys(data).forEach(key => { params = params.set(key, data[key]); }); } // 正确传递headers和params到请求选项中 return this.http.get(`${this.API_URL}${url}`, { headers, params }); } // 同样修复post方法,确保动态创建headers post(url: string, body: any): Observable<any> { const token = localStorage.getItem('token') || null; const headers = new HttpHeaders() .set('Content-Type', 'application/json') .set('Authorization', token ? `Bearer ${token}` : ''); return this.http.post(`${this.API_URL}${url}`, body, { headers }); } }
可选优化:维护GlobalHttp内部的token状态
如果不想每次请求都读localStorage,可以在GlobalHttp里维护token变量,并提供更新方法,登录后主动更新:
// 在GlobalHttpService中添加 token: string = localStorage.getItem('token') || null; updateToken(newToken: string | null): void { this.token = newToken; } // 然后在login函数的tap里调用 tap(data => { const token = data.token; this.setToken(token); this.globalHttp.updateToken(token); // 新增这行同步服务内的token this.router.navigateByUrl("/profiles-list"); }) // 此时get/post方法里的token直接用this.token即可 const headers = new HttpHeaders() .set('Content-Type', 'application/json') .set('Authorization', this.token ? `Bearer ${this.token}` : '');
额外注意点
你原代码中globalHttp.get的写法错误:this.http.get(this.API_URL + url + this._headers)——不能把headers直接拼到URL后面,应该作为请求选项的headers属性传递,这也是之前请求可能异常的原因之一。
内容的提问来源于stack exchange,提问作者Lucas Dmnt

