如何等待Fetch API返回值完成后再导出常量对象myUserState
问题核心原因
ES 模块的导出逻辑是同步执行的,在模块加载时就会完成,Fetch API 是异步网络请求,执行顺序必然晚于模块导出,不存在可以延迟导出的原生语法。
你当前代码观察到为空还有两个直接问题:
console.log('myUserState values: ', myUserState );放在了 Fetch 的 then 链外部、catch 之前,属于同步执行的代码,执行的时候请求还没有返回,自然打印的是空数组- 代码存在语法错误:console.log 的位置打断了 Promise 链,catch 的括号配对也不正确
可行的解决方案
方案1:导出带状态判断的访问方法,配合初始化调用
不直接导出固定的 myUserState 对象,改用访问器属性加加载状态标记,按需返回最新值:
const myPriv = []; // 新增标记判断请求是否完成 let privsLoaded = false; export const myUserState = { loggedIn: true, loggingIn: false, get myPrivs() { // 可根据业务需求自定义加载中阶段的返回值 return privsLoaded ? myPriv : []; } }; export const getPrivs = () => { const apiOptions = { method: 'GET', headers: { 'Content-Type': 'application/json' } }; return fetch(`${MY_ENDPOINT}/getMyPrivs`, apiOptions) .then(handleErrors) .then((response) => response.json()) .then((json) => { myPriv.push(json[0].privs); privsLoaded = true; // 只有在then链内打印才能拿到更新后的值 console.log('myUserState values: ', myUserState); }) .catch((error) => { console.log(error); }); }
使用时在应用初始化入口(比如 App 组件的 useEffect 中)先调用 getPrivs,后续访问 myUserState.myPrivs 就可以拿到最新的权限值。
方案2:适配React响应式更新,用Context托管状态
如果权限值需要在React组件中响应式渲染,普通的数组push不会触发组件重渲染,建议用React Context托管全局状态:
// PrivContext.jsx import { createContext, useContext, useEffect, useState } from 'react'; const PrivContext = createContext({ loggedIn: true, loggingIn: false, myPrivs: [] }); export const PrivProvider = ({children}) => { const [myPrivs, setMyPrivs] = useState([]); const [loggingIn, setLoggingIn] = useState(false); useEffect(() => { const getPrivs = async () => { setLoggingIn(true); try { const apiOptions = { method: 'GET', headers: { 'Content-Type': 'application/json' } }; const res = await fetch(`${MY_ENDPOINT}/getMyPrivs`, apiOptions); handleErrors(res); const json = await res.json(); setMyPrivs([json[0].privs]); } catch (e) { console.log(e); } finally { setLoggingIn(false); } }; getPrivs(); }, []); return ( <PrivContext.Provider value={{ loggedIn: true, loggingIn, myPrivs }} > {children} </PrivContext.Provider> ); }; export const usePriv = () => useContext(PrivContext);
在根组件包裹 PrivProvider 后,所有需要用到权限的组件直接调用 usePriv() 即可拿到响应式更新的权限值。
方案3:预请求权限再初始化应用
如果必须等权限加载完成再渲染整个应用,可以在入口文件先请求权限再挂载React根节点:
// index.jsx import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; const initApp = async () => { let initialPrivs = []; try { const apiOptions = { method: 'GET', headers: { 'Content-Type': 'application/json' } }; const res = await fetch(`${MY_ENDPOINT}/getMyPrivs`, apiOptions); handleErrors(res); const json = await res.json(); initialPrivs = [json[0].privs]; } catch (e) { console.log(e); } // 把预加载的权限作为初始值传入应用 const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<App initialPrivs={initialPrivs} />); }; initApp();
内容的提问来源于stack exchange,提问作者ArthurJ
相关产品推荐
相关产品推荐

