Search code examples
javascriptreact-nativeasync-awaites6-promisestack-navigator

How to await Promise without declaring async


I'm writing a React Native app. Is there a way to resolve Promise in non-async function before returning value?

Sample:

const f = () => {
  return new Promise((resolve) => {
    resolve('baz')
  })
}

const foo = () => {
  const a = f() // a is now a Promise
  return a
};

console.log(foo) // `foo` is a Promise, I need 'baz'

I would like to find a way to get the resolved value out of f, but I cannot make foo() async. Is there a way to achieve this? If not, any ideas how to go around this?

Here's my real code with some clean-up:

const stackNavigator = new StackNavigator(...)
const defaultGetStateForAction = stackNavigator.router.getStateForAction

stackNavigator.router.getStateForAction = (action, state) => {

  let screenToRequest = undefined
  let defaultState = undefined

  const isInitial = action.type === 'Navigation/INIT'

  if (isInitial) {
    defaultState = MainTabs.router.getStateForAction('Navigation/INIT')
    screenToRequest = defaultState.routes[defaultState.index].routeName
  } else if (action.type === 'Navigation/NAVIGATE') {
    screenToRequest = action.routeName
  }

  if (screenToRequest) {
    const screen = screens.getScreen(screenToRequest)

    /**
     * If screen requires login, check if user is logged in
     */
    if (screen.screen.loginRequired) {
      /**
       * Here I would like to read data from AsyncStorage with
       * `await` but that's not possible due to this function
       * not being `async` and it cannot be since router does not
       * seem to support it.
       *
       * getSession() reads data from AsyncStorage. If I could
       * `await getSession()`, I would not have a problem.
       */
       const session = getSession()

       // Use `session` to determine if user is logged and act accordingly
    }
  }

  return defaultGetStateForAction(action, state);
};

Solution

  • Quick & dirty: you could just turn foo() into a polling function.

    Just create a setInterval that polls every so often and checks for a value that is updated by f() when the Promise resolves.

    EDIT:

    I'm sorry, I think I misread your question. You cant make it async. Well, then you could just do this:

    const foo = async () =>{
      await const a = f() // a is now a Promise
      return a // a will not be returned until f() resolves
    };
    

    This will make the function synchronous (blocking). When you call it, you will want to await it as well if you need to maintain the synchronicity:

    {
      bar: async () =>{
        await foo();
        return; // dont return until foo() resolves
      }
    }