Search code examples
javascriptreactjsasynchronousreduxpromise

Wait until all subpromises are resolved


Let's say I have something like:

const exampleFunction = () => {
const fetchActions = someArray.map(() => {
                dispatch(action()).then(response => {
                    if (response?.data) {
                        dispatch(subAction({response: response.data}))
                    }
                })
            })

return Promise.all(fetchActions)
.then(()=> dispatch(finalAction()))
}

My problem is that when I dispatch my finalAction, all the actions have been dispatched/resolved but not the subActions. How can I execute my dispatch(finalAction())) ONLY when all the actions and subActions have been resolved?


Solution

  • The problem is Promise.all([...promises]) resolves when all promises resolve but your fetchActions is not really an array of promises (that you intended) because they have orphaned promises with the promise chain disconnected. In order to connect the chain again, you need to add return.

    const exampleFunction = () => {
      const fetchActions = someArray.map(() => {
        return dispatch(action()).then(response => {
          if (response?.data) {
            return dispatch(subAction({
              response: response.data
            }))
          }
        })
      })
    
      return Promise.all(fetchActions)
        .then(() => dispatch(finalAction()))
    }
    

    See here to learn more about promise chaining.


    Basically, the idea is: if you want a function to resolve after the promise called inside it is resolved, you need to return that promise.

    For example:

    const promiseA = () => {
      promiseY();
    };
    
    const promiseB = () => {
      promiseZ();
    };
    
    await Promise.all([promiseA(), promiseB()]);
    

    Promise.all above immediately resolves without waiting for promiseY or promiseZ because they're orphaned promises.

    In order to wait for them, it should be like this:

    const promiseA = () => {
      return promiseY();
    };
    
    const promiseB = () => {
      return promiseZ();
    };
    
    await Promise.all([promiseA(), promiseB()]);