Next.js中RxJS BehaviourSubject状态管理实现失效问题
问题:使用RxJS BehaviourSubject存储JWT后,生成Bearer Token时始终返回null
我尝试在登录时用RxJS BehaviourSubject存储JWT Token,以此给HTTP请求添加Authorization: Bearer ${user.jwtToken}请求头。我认为实现需要满足以下几点:
- 初始值
- 可转换为Observable的数据源
- 可订阅的公共变量
登录时已经通过userSubject.next(user);将用户信息正确传入subject,但每次生成Bearer Token时,accountService.userValue始终为null。
相关代码
账户服务
// 账户服务 // 初始化并设置初始值 const userSubject = new BehaviorSubject(null); const authApiUrl = "https:testApi"; export const accountService = { user: userSubject.asObservable(), get userValue() { return userSubject.value }, login, getAllUsers }; function login(email, password) { return fetchWrapper.post(process.env.AuthApiUrl + '/accounts/authenticate', { email, password }) .then(user => { userSubject.next(user); localStorage.setItem('user', JSON.stringify(user)); return user; }); } function getAllUsers() { return await fetchWrapper.get(process.env.AuthApiUrl + '/accounts/get-all-users'); // 语法错误:未声明async却使用await }
请求封装器
// 请求封装器 export const fetchWrapper = { get, post }; function post(url, body) { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeader(url) }, credentials: 'include', body: JSON.stringify(body) }; return fetch(url, requestOptions).then(handleResponse); } function get(url) { const requestOptions = { method: 'GET', headers: authHeader(url) }; return fetch(url, requestOptions).then(handleResponse); } function authHeader(url) { // 若用户已登录且请求指向API地址,则返回带基础认证凭证的请求头 // accountService.userValue 始终为null??? const user = accountService.userValue; const isLoggedIn = user && user.jwtToken; const isApiUrl = url.startsWith(process.env.AuthApiUrl); if (isLoggedIn && isApiUrl) { return { Authorization: `Bearer ${user.jwtToken}` }; } else { return {}; } } function handleResponse(response) { return response.text().then(text => { const data = text && JSON.parse(text); if (!response.ok) { if ([401, 403].includes(response.status) && accountService.userValue) { // 若API返回401未授权或403禁止响应,则自动登出 accountService.logout(); } const error = (data && data.message) || response.statusText; return Promise.reject(error); } return data; }); }
问题原因及修复方案
1. 页面刷新后未恢复用户状态
BehaviourSubject的初始值为null,页面刷新后会重置状态,导致userValue回到null。需要在初始化时从localStorage读取已保存的用户信息:
// 账户服务初始化逻辑修改 const storedUser = localStorage.getItem('user'); const userSubject = new BehaviorSubject(storedUser ? JSON.parse(storedUser) : null);
2. 模块循环引用问题
accountService依赖fetchWrapper,而fetchWrapper又依赖accountService,初始化时可能出现accountService未完全导出的情况,导致authHeader获取到的userValue为null。可以通过延迟导入避免循环引用:
function authHeader(url) { // 根据实际文件路径调整导入语句 const { accountService } = require('./accountService'); const user = accountService.userValue; // 后续逻辑保持不变 }
3. 修复getAllUsers语法错误
函数未声明async却使用await会触发语法错误,修改如下:
async function getAllUsers() { return await fetchWrapper.get(process.env.AuthApiUrl + '/accounts/get-all-users'); }
4. 验证登录返回数据结构
检查登录接口返回的user对象是否包含jwtToken字段,若返回数据结构不符,会导致isLoggedIn判断为false,无法生成Bearer Token。
内容的提问来源于stack exchange,提问作者ade
相关产品推荐
相关产品推荐

