Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
    })
    /** */
  })
}
like image 286
Rahul Yadav Avatar asked May 10 '18 19:05

Rahul Yadav


People also ask

How do you run multiple promises together?

Approach 1: In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.

How do you resolve an array of promises?

all() The Promise. all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.

Does promise all wait for all promises?

In other words, the Promise. all() waits for all the input promises to resolve and returns a new promise that resolves to an array containing the results of the input promises. In this diagram, the promise2 rejects at t1 with an error .

Does promise all use multiple threads?

Final Thoughts: Parallel ProcessingOften Promise. all() is thought of as running in parallel, but this isn't the case. Parallel means that you do many things at the same time on multiple threads. However, Javascript is single threaded with one call stack and one memory heap.


2 Answers

Promise.all returns a promise so you can do:

const p1 = Promise.all(PromiseArr1).then(...);
const p2 = Promise.all(PromiseArr2).then(...);
const p3 = ...
Promise.all([p1, p2, ...]).then(...);

If all your promises are very similar you can clean it up by creating an array and mapping it to the promises.

like image 189
Roy Wang Avatar answered Oct 10 '22 20:10

Roy Wang


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.

like image 37
Tyler Sebastian Avatar answered Oct 10 '22 20:10

Tyler Sebastian