Search code examples
javascriptreactjses6-promise

How to nest multiple Promise.all


I have multiple arrays of promises

Each array is put inside a Promise.all()

The then() of each Promise.all() adds data to a tempObject

I need to set the tempObject to state after then() of all Promise.all() are done executing.

What is the best approach (clean and readable code) to achieve this?

below is my code

callSomeApis(parameter){
  let tempArray1 = [];
  let tempArray2 = [];
  this.props.dispatch(actions.callApi1(parameter)).then(callApi1Result =>{
    let callApi1ResultArray = callApi1Result.data.data;
    let PromiseArr1 = callApi1ResultArray.map((callApi1ResultArrayItem) => {
      return this.props.dispatch(actions.callApi2(callApi1ResultArrayItem.itemId));
    });
    let PromiseArr2 = callApi1ResultArray.map((callApi1ResultArrayItem) => {
      return this.props.dispatch(actions.callApi3(callApi1ResultArrayItem.itemId,parameter));
    });
    let PromiseArr3 = callApi1ResultArray.map((callApi1ResultArrayItem) => {
      return this.props.dispatch(actions.callApi4(callApi1ResultArrayItem.itemId));
    });
    Promise.all(PromiseArr1).then((callApi2Result) => {
      callApi2Result.map((callApi2ResultItem,index) => {
        callApi1ResultArray[index].api2Details = callApi2ResultItem.data.data[0];
        tempArray2.push({id: callApi2ResultItem.data.data[0].id, text: callApi2ResultItem.data.data[0].text});
      });
      this.setState(prevState => {
        return{
          stateKey1: {
            ...prevState.stateKey1,
            innerStateKey1: {
              ...prevState.stateKey1.innerStateKey1,
              list: tempArray2
            }
          }
        }
      });
    });
    Promise.all(PromiseArr2).then((callApi3Result) => {
      callApi3Result.map((callApi3ResultItem, index) => {
        callApi1ResultArray[index].api3Result = callApi3ResultItem.data.data;
      });
    });
    Promise.all(PromiseArr3).then(callApi4Result => {
      callApi4Result.map((callApi4ResultItem,index) => {
        callApi1ResultArray[index].api4Result =  callApi4ResultItem.data.data;
      });
    });
    /**need to call this after the thens of  PromiseArr1, PromiseArr2 and PromiseArr3 are done executing*/
    this.setState({
      stateKey2:callApi1ResultArray
    })
    /** */
  })
}


Solution

  • If you're able, you can also use async/await

    async function (...) {
      const r1 = await Promise.all(...);
      // do something with r1
      const r2 = await Promise.all(...);
      // ...
    }
    

    and so on. Make sure you're using Promise.all on actions that can be parallelized (that also return a Promise), though.

    I find that async/await really cleans up some nasty Promise chains/nesting and helps a lot with readability.