Espere las iteraciones de array.map en Promise.all [duplicado]

Dec 06 2020

Tengo el siguiente código que debería agregar elementos para los clientes si aún no existen. La ejecución debe realizarse en paralelo.

await Promise.all(
    customers.map(async (customer) => {
        return customer.items.map(async (item) => {
            return new Promise(async (resolve) => {
                const productExists = someArray.some(
                    (arrayValue) => arrayValue === item.id
                );
                if (!productExists) {
                    logger.info(
                    `customer item ${item.id} does not exist, creating...` ); await createCustomerItem(item.id); logger.info(`customer item ${item.id} created.`);

                    someArray.push(item.id);
                } else {
                    logger.info(`customer item ${item.id} already exists, skipping...`);
                }
                resolve(true);
            });
        });
    })

);

logger.info(`All items should now be present`);

El problema es que la ejecución no está a la espera de createCustomerItemresolverse en los casos de!productExists)

Este es el registro

customer item 32310 does not exist, creating...
customer item ao does not exist, creating...
customer item ute does not exist, creating...
All items should not be present
customer item ao created.
customer item ute created.
customer item 32310 created.

Naturalmente, All items should not be presentdebería ser el último.

Cuando todos los elementos ya existen, el proceso se ve bien.

Respuestas

JulienD Dec 06 2020 at 18:46

Prueba con flatMap:

await Promise.all(
    customers.flatMap(async (customer) => {
        return customer.items.map(async (item) => {

En lugar de devolver un conjunto de promesas, aplanará el contenido a un conjunto simple de promesas, que es lo que se Promise.allespera.

NB De su pregunta no resulta evidente si es necesario conservar la agrupación de artículos por cliente. Si es así, tenga en cuenta que esta solución cambia la estructura de datos a una lista plana, por lo que pierde la agrupación. Agregue algunos customerIden sus itemmensajes de correo electrónico o pruebe la sugerencia de @ blex en los comentarios.

ShashanSooriyahetti Dec 06 2020 at 18:56

puedes hacer algo como esto

const fruitsToGet = ['apple', 'grape', 'pear']

const mapLoop = async () => {
  console.log('Start')

  const promises = await fruitsToGet.map(async fruit => {
    const numFruit = new Promise((resolve, reject) => {
      setTimeout(() => resolve(fruit), 1000)
    });
    return numFruit
  })
  const numFruits = await Promise.all(promises)
  console.log(numFruits)

  console.log('End')
}

mapLoop();

resultados

Start
["apple", "grape", "pear"]
End

demostración de la fuente