Constantin
Constantin

Reputation: 21

Is there an advantage to using an otherwise synchronous function inside a Promise.all?

Say I have a synchronous function like this:

function sumTotal(items) {
  return items.reduce((total, item) => item.price + total)
}

And it is used after a Promise.all containing some asynchronous API calls within this 'checkout' function

function checkout(items) {
  return Promise.all([
    getLatestOffers(),
    getCustomerDetails('[email protected]')
  ]).then(([offers, details]) => {
    return { offers, details, total: sumTotal(items) }
  });
}

Is there be any advantage, performance wise or other, to changing the sumTotal function to return a promise and calling it in the Promise.all like this?

function checkOut(items) {
  return Promise.all([
    getLatestOffers(),
    getCustomerDetails('[email protected]'),
    sumTotal(items)
  ]).then(([offers, details, total]) => {
    return { offers, details, total }
  });
}

Upvotes: 0

Views: 38

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371079

Either method works. Because sumTotal is synchronous, it won't matter in most cases. The only time it might matter is if items is an unreasonably huge array, and iterating over it takes a not-insignificant amount of CPU time - in which case, it would be better to call sumTotal with Promise.all so that it can resolve immediately once the promises resolve, rather than having to wait for an expensive operation after the other promises resolve.

But, keep in mind that Promise.all accepts non-Promises as well: there's no need to convert sumTotal to something that returns a Promise.

Also, if items is an array of objects with a price property, make sure to provide reduce with an initial value, else you might end up with something like [Object object]102030 for your total:

const somethingAsync = () => new Promise(res => setTimeout(res, 500, 'foo'));

function sumTotal(items) {
  return items.reduce((total, item) => item.price + total, 0)
}
function checkOut(items) {
  return Promise.all([
    somethingAsync(),
    somethingAsync('[email protected]'),
    sumTotal(items)
  ]).then(([offers, details, total]) => (
    { offers, details, total }
  ));
}

console.log('start');
checkOut([{ price: 10 }, { price: 20 }])
  .then(output => console.log(output));
  

Upvotes: 3

Related Questions