Reactjs 如何将此创建存储转换为基于承诺的存储?

Reactjs 如何将此创建存储转换为基于承诺的存储?,reactjs,typescript,firebase,firebase-realtime-database,Reactjs,Typescript,Firebase,Firebase Realtime Database,我的应用程序最初是从本地存储加载数据,现在我尝试使用firebase。 Firebase总是倾向于回报承诺。因此,我正在尝试将商店转换为firebase return one 这是原件 export const loadState = () => { const state: AppState = getDefaultState(); VALID_LABS.forEach(labId => { state.labs[labId] = getDefaultLabStat

我的应用程序最初是从本地存储加载数据,现在我尝试使用firebase。 Firebase总是倾向于回报承诺。因此,我正在尝试将商店转换为firebase return one

这是原件

export const loadState = () => {
  const state: AppState = getDefaultState();
  VALID_LABS.forEach(labId => {
    state.labs[labId] = getDefaultLabState();
    STORAGE_CONFIG.forEach(storageField => {
      const { statePath, storageKey, defaultValueFn } = storageField;
      const loadedValue = getFromLocalStorage(
        labId,
        storageKey,
        defaultValueFn()
      );
      cachedValues[`${labId}:${storageKey}`] = loadedValue;
      set(state, `labs.${labId}.${statePath}`, loadedValue);
    });
  });
  return state as AppState;
};

正如你们所看到的,我正在使这个过程运转良好。但当我开始使用firebase时,问题就出现了

我的状态变成这样

export const loadState = (): AppState => {
  if (firebase.auth().currentUser.uid) {
    let userId = firebase.auth().currentUser.uid;
    return firebase
      .database()
      .ref('/users/' + userId)
      .once('value')
      .then(function(snapshot) {
        return snapshot.val() as AppState;
      }).catch((err) => {
        console.error(err)
      })
  }
};
因此,我还需要转换
存储
以接受从新的
加载状态返回的
承诺
。 我不知道如何转换它,因为我也在使用
applyMiddleWare(thunk)


首先,有一个小错误,您可能应该在catch块的末尾抛出err,如果您不这样做,错误将被视为已处理,从catch返回的任何内容都将被视为承诺的价值。在这种情况下,它是
未定义的
,因此如果发生错误,
加载状态
将解析为
未定义,而不是
应用状态
对象,这可能会导致一些问题,但这取决于您,也许您有其他计划如何处理此问题

不管怎么说,承诺的问题在于,一旦一个函数开始使用它,其他所有函数都必须使用它。更简单的选择是在异步函数中创建存储:

function createStore() {
  return loadState()
    .then(state => {
      const store = createStore(rootReducer, state, applyMiddleware(thunk))
      // Either subscribe to store here
      return store
    })
}

const storePromise = createStore()
// or here
/* storePromise.then(store => store.subscribe(...))
或者使用
async/await

async function createStore() {
  const state = await loadState()
  return createStore(rootReducer, state, applyMiddleware(thunk))
}
const storePromise = createStore()
很难判断这是否适合您的应用程序,根据标签判断,您正在使用react,因此您可能需要添加额外的逻辑来加载此存储,例如编写一个
StoreProvider
并用它包装您的
应用程序

function StoreProvider({ children }: { children?: ReactNode }) {
  const [store, setStore] = useState<Store<AppState> | null>(null)

  useEffect(() => {
    createStore().then(setStore)
  }, [])

  if(!store) return <Loading /> // or whatever
  return <Provider store={store}>{children}</Provider>
}
函数存储提供程序({children}:{children?:ReactNode}){
const[store,setStore]=useState(null)
useffect(()=>{
createStore()。然后(设置存储)
}, [])
如果(!store)返回//或其他内容
返回{children}
}
这对你来说可能是好的,也可能不是。通常这不是很好,因为当
firebase
正在加载其内容时,您的应用程序无法渲染。另一种解决方案是在开始时以空状态初始化存储,呈现应用程序中不需要firebase人员的部分,并让其他人等待加载,您可以为此使用
thunk
s或创建三个操作
load\u store/REQUEST
load\u store/SUCCESS
加载存储/错误
并以适当的方式呈现应用程序。你可以创建一个系统,在加载过程中对一些需要存储的操作进行排队,并在加载完成后自动执行这些操作,这里有很大的创造力和挫败感空间,设计异步存储是一个相当大的挑战,您需要根据应用程序的需要决定如何实现它

async function createStore() {
  const state = await loadState()
  return createStore(rootReducer, state, applyMiddleware(thunk))
}
const storePromise = createStore()
function StoreProvider({ children }: { children?: ReactNode }) {
  const [store, setStore] = useState<Store<AppState> | null>(null)

  useEffect(() => {
    createStore().then(setStore)
  }, [])

  if(!store) return <Loading /> // or whatever
  return <Provider store={store}>{children}</Provider>
}