React页面刷新时useEffect异步函数未调用getSUserDetails问题
页面刷新时
getSUserDetails未触发的排查与解决 核心排查方向
1. 本地缓存存在,直接跳过API分支
fetchWalletAddress逻辑优先读取localStorage中的SINGULARITY_ACCOUNT_DATA,如果刷新时该缓存未过期或未被清除,会直接返回缓存地址,不会进入调用getSUserDetails的分支。
验证方式:
打开浏览器控制台(F12)→ 切换到Application标签 → 找到Local Storage,检查是否存在SINGULARITY_ACCOUNT_DATA键。若存在,删除后刷新页面,观察getSUserDetails是否触发。
优化方案:
给缓存添加有效期判断,避免无效缓存一直生效:
export const fetchWalletAddress = async () => { const storedData = localStorage.getItem("SINGULARITY_ACCOUNT_DATA"); if (storedData) { const parsedData = JSON.parse(storedData); const now = Date.now(); // 设置1小时有效期,可根据需求调整 if (parsedData.expireTime && now < parsedData.expireTime) { const addressFromStorage = parsedData?.gamePayWallet?.accounts.evmPublicAddress[0].publicAddress; return Promise.resolve(addressFromStorage); } else { // 缓存过期,删除后走API逻辑 localStorage.removeItem("SINGULARITY_ACCOUNT_DATA"); } } // 缓存不存在/过期,调用API获取数据 return getSUserDetails() .then(async (data) => { console.log("User data", data); let addressToSet; if (data) { addressToSet = JSON.parse(data).wallet.accounts.evmPublicAddress[0].publicAddress; } else { const loginData = await handleWaitingEvent("login"); addressToSet = loginData.wallet.accounts.evmPublicAddress[0].publicAddress; } // 存入带有效期的缓存 localStorage.setItem("SINGULARITY_ACCOUNT_DATA", JSON.stringify({ gamePayWallet: JSON.parse(data).wallet, expireTime: Date.now() + 3600 * 1000 })); return addressToSet; }) .catch((error) => { console.log("Error while fetching data from API", error); throw error; }); };
2. window.SEvent刷新后未就绪,导致getSUserDetails静默失败
页面刷新后,window.SEvent可能还未完成初始化,此时调用window.SEvent.getConnectUserInfo()会报错,但getSUserDetails的catch块仅打印日志,容易被忽略,误以为函数未被调用。
验证方式:
查看浏览器控制台是否存在Error User Details ->开头的错误日志。
优化方案:
等待SEvent初始化完成后再执行逻辑:
export const getSUserDetails = async () => { // 等待SEvent全局对象就绪 if (!window.SEvent) { await new Promise(resolve => { // 轮询检查,每100ms一次 const checkInterval = setInterval(() => { if (window.SEvent) { clearInterval(checkInterval); resolve(); } }, 100); }); } try { const user = await window.SEvent.getConnectUserInfo(); return JSON.stringify(user.metaData); } catch (err) { console.error("Error User Details ->", err); throw err; } };
如果SEvent提供了初始化完成的事件(如s-event-ready),也可以用事件监听替代轮询:
export const getSUserDetails = async () => { if (!window.SEvent) { await new Promise(resolve => { window.addEventListener('s-event-ready', () => resolve(), { once: true }); }); } // 后续逻辑不变 };
3. 补充:Promise嵌套逻辑优化
原代码中addressToSet在data为空时返回Promise嵌套,虽不影响函数调用,但可能导致后续处理异常,建议改为async/await写法(如上述优化方案中的代码)。
内容的提问来源于stack exchange,提问作者Jai
相关产品推荐
相关产品推荐

