简体   繁体   中英

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);
};

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

\n

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
  }
}

It feels like you may want to rethink your architecture a bit. If you are performing an operation (lets say a network request) that other parts of your app need that data in order to function, then you only have two choices. You can either halt everything and wait (async/await), or you can let your app gracefully continue without that data, then update itself once it becomes available. Both options are great, and it only depends on what exactly you are trying to do.

In a React/React Native app, the second option is used quite frequently when you have a UI that is waiting for data to come back from a network request. Instead of freezing the UI while you make the request, you render the UI with some message that says the data is coming. In your async function when the promise is resolved, you have to put that data somewhere that your patient UI can read from. This is where state management systems like Redux or Mobx come in. They give you a place to store that data, then they dispatch the event to alert your UI that you are ready and you can now re-render with all that beautiful data.

Hope that helps in some way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM