skip to Main Content

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?

2

Answers


  1. The problem with your code is that you are not returning anything from the someArray.map callback, which means that fetchActions is an array of undefined values, not promises. Therefore, Promise.all will not wait for the dispatch actions or subActions to finish before resolving.

    To fix this problem, you can try this:

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

    In this code, someArray.map doesn’t return anything, but it makes an array of promises. Each promise waits for the last await inside the map function, which is either dispatch(subAction()) or undefined. It’s like returning an array of those values as promises.


    If you want to make it more explicit, you can add a return statement inside the map callback, like this:

    const fetchActions = someArray.map(async () => {
      const response = await dispatch(action());
      if (response?.data) {
        return dispatch(subAction({ response: response.data }));
      }
      return undefined;
    });
    
    Login or Signup to reply.
  2. 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()]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search