Skip to content
Advertisement

Resolving an array or promises and getting the result

I’m attempting to map and format data to render it into a table. I have an array of promises that I’m attempting to resolve with Promise.all(). but it seems to not be returning the result of the promise.

my code is as follows:

const formatData = (data) => {
  let dataCopy = data;

  if (dataCopy.items && _.has(dataCopy.items[0], 'tenantId')) {
      dataCopy.items = setTenants(dataCopy)
  }

  // format parameters or table render
  // other formatting for the table
  return dataCopy.items.map(item => ({
      ...item,
      created: new Date(item.created).toDateString(),
      updated: new Date(item.updated).toDateString(),
      ...(item.active && { active: item.active.toString() })
  }));
};

const setTenants = (data) => {
  const promises = data.items.map(item => {
      return getTenant(item)
  })
  return Promise.all(promises).then(res => { return res })
}

const getTenant = (row) => {
  return tenantService.getTenantById(row.tenantId).then(res => {
      // set name as the tenant param for the table
      row.tenant = res.name
      return row
  });
}

my data copy variable only returns as :

[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(10)

where the result is the correct result of the ‘setTenants’ function.

Advertisement

Answer

I have an array of promises that I’m attempting to resolve with Promise.all().

Promise.all doesn’t resolve promises (or I think you mean settle¹ in this case). It allows you to observe the result of promises being settled. It doesn’t make them settle.

Your setTenants function returns a promise. To use its fulfillment value, you have to use .then or await (in an async function). Remember that as of when setTenants returns its promise, the operations that have been started may not have completed yet.

So

setTenants(/*...*/)
.then(results => {
    // use results...
})
.catch(error => {
    // handle/report error
});

Or, in an async function:

const results = await setTenants(/*...*/);

(Perhaps with a try/catch to handle rejection, although often you’ll want to just let that propagate to the caller and handle it there.)


Side note: The then callback in this code is pointless:

return Promise.all(promises).then(res => { return res })

It should just be:

return Promise.all(promises);

¹ Some promise terminology:

  • fulfill – To change a promise state from pending to fulfilled with a specific fulfillment value
  • reject – To change a promise state from pending to rejected with a specific rejection reason
  • resolve – To determine the eventual outcome of a promise, either directly (by fulfilling or rejecting it) or indirectly (by making its outcome depend on the outcome of another promise)

It’s important to realize that a resolved promise will still be pending if it’s resolved to another promise and that other promise is pending.

Here’s an example:

const p1 = new Promise(resolve => {
    setTimeout(resolve, 800, 42);
});

// This could also be written: `const p2 = Promise.resolve(p1);`
const p2 = new Promise(resolve => {
    resolve(p1);
});

// At this point, both `p1` and `p2` are *pending*; `p2` is *resolved to*
// `p1`, but neither `p1` nor `p2` is *settled* yet

p2
.then(value => {
    // At this point, `p2` is *fulfilled* (one of the two kinds of *settled*)
    console.log(value);
})
.catch(error => {
    // At this point, `p2` is *rejected* (one of the two kinds of *settled*)
    console.error(error);
});
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement