You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 01:27:01