Warten Sie auf Array.map-Iterationen in Promise.all [duplizieren]

Dec 06 2020

Ich habe den folgenden Code, der Artikel für Kunden hinzufügen soll, falls diese noch nicht vorhanden sind. Die Ausführung sollte parallel erfolgen.

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`);

Das Problem ist, dass die Ausführung createCustomerItemin den Fällen von nicht auf eine Lösung wartet!productExists)

Dies ist das Protokoll

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.

Natürlich All items should not be presentsollte zuletzt kommen.

Wenn alle Elemente bereits vorhanden sind, sieht der Prozess gut aus.

Antworten

JulienD Dec 06 2020 at 18:46

Versuchen Sie mit flatMap:

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

Anstatt ein Array von Versprechungen zurückzugeben, wird der Inhalt auf ein einfaches Versprechungsarray reduziert, was Promise.allerwartet wird.

NB Aus Ihrer Frage geht nicht hervor, ob die Gruppierung von Artikeln pro Kunde beibehalten werden muss. Wenn dies der Fall ist, beachten Sie, dass diese Lösung die Datenstruktur in eine reduzierte Liste ändert, sodass Sie die Gruppierung verlieren. Fügen Sie entweder einige customerIdin Ihr items ein oder versuchen Sie den Vorschlag von @ blex in den Kommentaren.

ShashanSooriyahetti Dec 06 2020 at 18:56

Sie können so etwas tun

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();

Ergebnisse

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

Quelle Demo