How Can I Unwrap an Array of Promises within a Chain of Array Methods? Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of How Can I Unwrap an Array of Promises within a Chain of Array Methods? without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I have a chain of several maps, one of which needs to perform a database operation for each array element, so I’m using async await.

const resultsAsPromises = arr
  .map(syncDouble)
  .map(asyncMapper)

This isn’t a problem if it is the last item in the chain because I can unwrap it with Promise.all

console.log('results', await Promise.all(resultsAsPromises))

However, there are other synchronous operations I need to perform afterward, so I’d like to have the promises’ values unwrapped before moving on to the next .map.

Is there a way to do this? I thought perhaps just making an extraction mapper like

function extractPromiseValues(value) {
  return value.then(v => v);
}

would work, but alas, no.

var arr = [1, 2, 3, 4, 5];
function timeout(i) {
  return new Promise((resolve) => {
    setTimeout(() => {
      return resolve(`number is ${i}`);
    }, 1);
  });
}

function syncDouble(i) {
  return i * 2;
}

async function asyncMapper(i) {
  return await timeout(i)
}

function extractPromiseValues(value) {
  return value.then(v => v);
}
async function main() {
  const resultsAsPromises = arr
    .map(syncDouble)
    .map(asyncMapper)
//     .map(extractPromiseValues)
  console.log('results', await Promise.all(resultsAsPromises))
}

main();

How can I unwrap an array of promises within a chain of array methods

Answer

Rather than passing an identity function to .then(), pass your synchronous operation instead, OR await the promise in an async function before passing it to your synchronous operation:

function syncCapitalize(s) {
  return s.slice(0, 1).toUpperCase() + s.slice(1);
}

const resultsAsPromises = arr
  .map(syncDouble)
  .map(asyncMapper)
  .map(p => p.then(syncCapitalize)); // OR
//.map(async p => syncCapitalize(await p));

In the context of your example, this would look like:

function timeout(i) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(`number is ${i}`);
    }, 1);
  });
}

function syncDouble(i) {
  return i * 2;
}

function asyncMapper(i) {
  return timeout(i);
}

function syncCapitalize(s) {
  return s.slice(0, 1).toUpperCase() + s.slice(1);
}

async function main() {
  const arr = [1, 2, 3, 4, 5];
  const resultsAsPromises = arr
    .map(syncDouble)
    .map(asyncMapper)
    .map(p => p.then(syncCapitalize)); // OR
  //.map(async p => syncCapitalize(await p));

  console.log('results', await Promise.all(resultsAsPromises));
}

main();

Alternatively, if we are interpreting the question as Ghassen Louhaichi has, you could use the TC39 pipeline operator (|>) proposal to write the chain using one of the options below:

F# Pipelines Proposal

const results = arr
  .map(syncDouble)
  .map(asyncMapper)
  |> Promise.all
  |> await
  .map(syncCapitalize);

Smart Pipelines Proposal

const results = (arr
  .map(syncDouble)
  .map(asyncMapper)
  |> await Promise.all(#))
  .map(syncCapitalize);

Unfortunately, unless you are using a Babel plugin, or until one of these proposals is merged into the official ECMAScript specification, you have to wrap the chain with await Promise.all(...):

const results = (await Promise.all(arr
  .map(syncDouble)
  .map(asyncMapper)))
  .map(syncCapitalize);

Finally, in the context of your full example:

function timeout(i) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(`number is ${i}`);
    }, 1);
  });
}

function syncDouble(i) {
  return i * 2;
}

function asyncMapper(i) {
  return timeout(i);
}

function syncCapitalize(s) {
  return s.slice(0, 1).toUpperCase() + s.slice(1);
}

async function main() {
  const arr = [1, 2, 3, 4, 5];
  const results = (await Promise.all(arr
    .map(syncDouble)
    .map(asyncMapper)))
    .map(syncCapitalize);

  console.log('results', results);
}

main();
We are here to answer your question about How Can I Unwrap an Array of Promises within a Chain of Array Methods? - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji