Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promise.all with nested Promise.all

I've nested arrays, I'm able to retrieve promises for the 2nd level array but not sure how to implement a then once top level finishes as well.

result.forEach(function(entity){ // outer list ???
    return Promise.all(entity.urls.map(function(item){
        return requestURL(item.href);
    }));
});

for instance if results has two or more items and each item has 10 or more urls to fetch, how would we implement then of [Promise.all][1] for all the promises. Native solution please.

Basically to handle nested arrays of promises in a right way.

Data Structure:

var result = [
    {
        urls: [
            {href: "link1"},
            {href: "link2"},
            {href: "link3"}
        ]
    },
    {
        urls: [
            {href: "link4"},
            {href: "link5"},
            {href: "link6"}
        ]
    }
];
like image 256
user2727195 Avatar asked Jul 18 '16 02:07

user2727195


People also ask

Can Promise be nested?

Nested Promise: In a promise nesting when you return a promise inside a then method, and if the returned promise is already resolved/rejected, it will immediately call the subsequent then/catch method, if not it will wait. If promised is not return, it will execute parallelly.

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 . Therefore, the Promise.

Does Promise all run promises in parallel?

all executes them in parallel.

What is the difference between Promise all and Promise allSettled?

allSettled() method is that unlike the previous method, Promise. all() , this will not fail once the first promise is rejected. Instead, it'll return a list of values.


1 Answers

Use map instead of forEach, and wrap it inside another Promise.all call.

var arr = [
  {subarr: [1,2,3]},
  {subarr: [4,5,6]},
  {subarr: [7,8,9]}
];
function processAsync(n) {
  return new Promise(function(resolve) {
    setTimeout(
      function() { resolve(n * n); },
      Math.random() * 1e3
    );
  });
}
Promise.all(arr.map(function(entity){
  return Promise.all(entity.subarr.map(function(item){
    return processAsync(item);
  }));
})).then(function(data) {
  console.log(data);
});

You can also use an immediately invoked generator. For example, to get flattened results,

var arr = [
  {subarr: [1,2,3]},
  {subarr: [4,5,6]},
  {subarr: [7,8,9]}
];
function processAsync(n) {
  return new Promise(function(resolve) {
    setTimeout(
      function() { resolve(n * n); },
      Math.random() * 1e3
    );
  });
}
Promise.all(function*() {
  for(var entity of arr)
    for(var item of entity.subarr)
      yield processAsync(item);
}()).then(function(data) {
  console.log(data);
});
like image 174
Oriol Avatar answered Oct 12 '22 22:10

Oriol