How to resolve nested promises?

Viewed 313

I'm trying to resolve multiple promises scattered across objects inside an array. Here is a simplistic version of my code:

const getOrderSum = order_id => {
    return new Promise(resolve => {
        setTimeout(() => resolve(34), 1000)
    })
}

const customer_array = [
    {
        customer_id: '19847743234730384',
        name: 'Customer 1',
        orders: [
            {
                order_id: '98749873244324',
                price_per: 12
            },
            {
                order_id: '9874987323545',
                price_per: 16
            }
        ]
    },
    {
        customer_id: '123454351234123',
        name: 'Customer 2',
        orders: [
            {
                order_id: '918741433423',
                price_per: 6
            }
        ]
    }
]

const result_array = customer_array.map(customer => {
    const promises = customer.orders.map(async order => {
        order.order_total = await getOrderSum();
        return order;
    });

    customer.orders = promises;
    return customer;
})

console.log(result_array);

Inside the map loops I want to make a call to an async function that returns an order_total for each order. result_array looks like this after the code runs:

[
  {
    customer_id: '19847743234730384',
    name: 'Customer 1',
    orders: [ [Promise], [Promise] ]
  },
  {
    customer_id: '123454351234123',
    name: 'Customer 2',
    orders: [ [Promise] ]
  }
]

How do I resolve all of those 3 promises at once and get this:

[
    {
        customer_id: '19847743234730384',
        name: 'Customer 1',
        orders: [
            {
                order_id: '98749873244324',
                price_per: 12,
                order_total: 34
            },
            {
                order_id: '9874987323545',
                price_per: 16,
                order_total: 34
            }
        ]
    },
    {
        customer_id: '123454351234123',
        name: 'Customer 2',
        orders: [
            {
                order_id: '918741433423',
                price_per: 6,
                order_total: 34
            }
        ]
    }
]

Where would I use Promise.all considering that the promises are not in one array?

3 Answers

Please check the code below:

const getOrderSum = order_id => {
  return new Promise(resolve => {
    setTimeout(() => resolve(34), 1000)
  })
}

const customer_array = [{
    customer_id: '19847743234730384',
    name: 'Customer 1',
    orders: [{
        order_id: '98749873244324',
        price_per: 12
      },
      {
        order_id: '9874987323545',
        price_per: 16
      }
    ]
  },
  {
    customer_id: '123454351234123',
    name: 'Customer 2',
    orders: [{
      order_id: '918741433423',
      price_per: 6
    }]
  }
]

let promises = [];
const result_array = customer_array.map(customer => {
  customer.orders.map((order) => {
    const p = getOrderSum().then((order_total) => {
      order.order_total = order_total;
    });
    promises.push(p);
    return order;
  });
  return customer;
});

Promise.all(promises).then(() => {
  console.log(result_array)
});

  1. Make customer_array.map as async.
  2. Use await Promise.all with customer.orders.map so that it will return result instead of Promise.
  3. As we have make customer_array.map as async and it is not wrapped inside async function so we need to resolve it with Promise.all().then(). Write your required code inside then.

Try it below.

const getOrderSum = order_id => {
  return new Promise(resolve => {
    setTimeout(() => resolve(34), 1000)
  })
}

const customer_array = [{
    customer_id: '19847743234730384',
    name: 'Customer 1',
    orders: [{
        order_id: '98749873244324',
        price_per: 12
      },
      {
        order_id: '9874987323545',
        price_per: 16
      }
    ]
  },
  {
    customer_id: '123454351234123',
    name: 'Customer 2',
    orders: [{
      order_id: '918741433423',
      price_per: 6
    }]
  }
]

const promises = customer_array.map(async customer => {
  customer.orders = await Promise.all(customer.orders.map(async order => {
    order.order_total = await getOrderSum();
    return order;
  }));
  return customer;
});

Promise.all(promises).then(results => console.log(results));

You can use promise.all for that and then use use .then method to resolve the value

Related