开发者问题收集

获取未返回承诺的函数的返回值

2018-03-16
528

我将我的 firebase api 调用从我的 react native 组件中抽象出来,放到一个服务层。这对于返回承诺的调用很有效,但这个调用 onAuthStateChanged 不会返回承诺。 如果没有服务层,我只会这样做:

firebase.auth().onAuthStateChanged(user => {
if (user) {
   //logged in 
} else { //not logged in  }

现在我想把所有东西都放在我的 services/api.js 中,我已经尝试了几种方法,但最新的是:

    export const userLoggedin = () => {
    firebase.auth().onAuthStateChanged(user => {
        if (user) {
            return true
        } else {
            return false
        }
    })
}

然后在我的 app.js 中我想检查 userLoggedin 是否返回 true 或 false,这样我就可以根据用户是否已经登录来导航用户。

    if (userLoggedin()) {
    // logged in 
} else {
    // logged out
}

现在最后一部分总是在 else 中,因为 userLoggedin 稍后会返回 true,并且它不会等待它。 这个问题有什么好的解决方案吗?

2个回答

您可以围绕不支持承诺的调用创建一个承诺:

export const userLoggedIn = () => {
  return new Promise((resolve, reject) => {
    firebase.auth().onAuthStateChanged(user => {
      resolve(!!user);
    })
  });
}
Nicholas Tower
2018-03-16

尽管承诺 适用于 一次性检查,但身份验证状态可能会在应用程序的生命周期内多次更改,例如,如果用户决定稍后退出。这样,您的应用程序可能会在 Firebase 检查完用户是否已登录之前实际呈现,从而导致身份验证检查错误,即使他们实际上已登录。

这是我建议的方法:使用组件状态来跟踪当前用户,以及当前是否正在检查身份验证状态。

注意:这是可靠的,因为 onAuthStateChanged 回调 始终 会触发至少一次。如果身份验证检查首先完成,则回调将在附加后立即被调用。

import React from 'react'
import firebase from 'firebase'

class App extends React.Component {
  state = {
    authenticating: true,
    user: null,
  }

  componentDidMount() {
    firebase.auth().onAuthStateChanged(user => {
      this.setState({ user, authenticating: false })
    })
  }

  render() {
    if (this.state.authenticating) {
      // we're still checking the auth state,
      // maybe render a "Logging in..." loading screen here for example
      return <LoadingScreen />
    }

    if (this.state.user === null) {
      // not logged in
      return <Redirect to='login' />
    }

    // here, auth check is finished and user is logged in, render normally
    return <AppContent />
  }
}

另外,附注:如果您确实想在应用中的某个地方检查用户当前是否已登录, firebase.auth().currentUser !== null 也可以正常工作。

kingdaro
2018-03-16