Search code examples
reactjsasynchronouspromisereduxredux-thunk

How to Chain Dynamic Series of Async Actions Using Redux Thunk?


The Norm

According to the official documentation (https://github.com/gaearon/redux-thunk), I know that redux thunk allows dispatching a chain of async actions sequentially like so:

function makeSandwichesForEverybody() {
  return function (dispatch, getState) {
    return dispatch(
      makeASandwichWithSecretSauce('My Grandma')
    ).then(() =>
      Promise.all([
        dispatch(makeASandwichWithSecretSauce('Me')),
        dispatch(makeASandwichWithSecretSauce('My wife'))
      ])
    ).then(() =>
      dispatch(makeASandwichWithSecretSauce('Our kids'))
    ).then(() =>
      dispatch(getState().myMoney > 42 ?
        withdrawMoney(42) :
        apologize('Me', 'The Sandwich Shop')
      )
    );
  }
}

My Situation

However, what if I have a dynamic array of actions that I want to iterate through and call?

let arrOfActions = [];
arrOfActions.push(action1);
arrOfActions.push(action2);
arrOfActions.push(action3);

How can I chain these async actions iteratively using Promise logic? To best explain what I am thinking, I am hoping to do something like this:

function thunkActionCreator() {
  return function (dispatch, getState) {
    for (let key of arrOfActions) {
      dispatch(arrOfActions[key]()).then(
        // run next action in arrOfActions here
      )
    }
  }
}

Is this dynamic iteration of function calls possible? If so, what is the syntax?

For verification that you can indeed call functions in an array of functions, here is the resource I found: How to store functions into an array and loop through each in javascript

Why A Dynamic Array of Actions?

There may be a better way to think of this, but the reason I am trying to use this implementation is because I have a series of functions that I need to call in a specific order. This array would be stored in Redux's store, and I am not sure how else to be able to call a series of functions in order from start to finish. Any other ideas would be helpful!


Solution

  • Upfront disclaimer; I think the fact that you need to do this is evidence of deeper problems in your codebase. You really shouldn't be queueing up a list of async functions that need to occur in a specific order and which you don't know of in advanced. That's a number of red flags.

    But can you do it? Sure!

    function enqueueDynamicArray(functionArray) {
        let p = Promise.resolve();
        for(index in functionArray) {
            p = p.then(functionArray[index]);
        }
        return p;
    }
    

    EDIT: And per comments, if you can rely on the functions being synchronous;

    function callDynamicArray(functionArray) {
        for(index in functionArray){
            functionArray[index]();
        };
    }