JS async function awaits forever

时间:2018-06-04 16:45:04

标签: javascript async-await

I have read a lot about async await, but apparently I still don't get it. ;-)

I am trying to transform the following .then promise structure into async await:

componentDidMount() {
    const { store } = this.props

    Promise.all([
      API.fetchTodos(),
      API.fetchGoals(),
    ]).then(([ todos, goals ]) => {
      store.dispatch(receiveDataAction(todos, goals))
    })

    store.subscribe(() => this.forceUpdate())

    console.log('test')
}

My result is:

async componentDidMount() {
    const { store } = this.props

    const [todos, goals] = await Promise.all([
      API.fetchTodos(),
      API.fetchGoals(),
    ])

    store.dispatch(receiveDataAction(todos, goals))

    store.subscribe(() => this.forceUpdate())

    console.log('test')
}

The result is that this function never ends. It calls everything including the console.log, but then the program just stops (no error). I'm not showing you any other parts of the application because according to my understanding these two functions should be equivalent - so the rest should not matter. Apparently I am wrong! :-) What am I doing wrong and why doesn't my solution work?

1 个答案:

答案 0 :(得分:5)

The difference between your two snippets is that in the second async/await example, you don't subscribe to the store until after you've fetched the goals and todos, whereas in the first, you subscribe immediately.

So your second example isn't working since now you've guaranteed that

store.dispatch(receiveDataAction(todos, goals))

is called before

store.subscribe(() => this.forceUpdate())

and since the action has already been dispatched by that point, the subscription callback is never called.

To fix that, you might just want to move the subscription part so that it occurs before the await call. That way you are already subscribed before the promise has resolved. So something like this:

async componentDidMount() {
    const { store } = this.props

    // Move to the front so this happens before the await.
    store.subscribe(() => this.forceUpdate())

    const [todos, goals] = await Promise.all([
      API.fetchTodos(),
      API.fetchGoals(),
    ])

    store.dispatch(receiveDataAction(todos, goals))

    console.log('test')
}