Promise.allでarray.mapの反復を待つ[重複]

Dec 06 2020

顧客がまだ存在しない場合にアイテムを追加する必要がある次のコードがあります。実行は並行して行う必要があります。

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

問題は、次の場合に実行がcreateCustomerItem解決を待機していないことです。!productExists)

これはログです

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.

当然All items should not be present最後に来るはずです。

すべてのアイテムがすでに存在する場合、プロセスは良好に見えます。

回答

JulienD Dec 06 2020 at 18:46

試してみてくださいflatMap:

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

Promisesの配列の配列を返す代わりに、コンテンツをPromisesの単純な配列にフラット化しますPromise.all。これは期待されることです。

注意:顧客ごとのアイテムのグループ化を維持する必要があるかどうかは、あなたの質問からは明らかではありません。含まれている場合、このソリューションはデータ構造をフラット化されたリストに変更するため、グループ化が失われることに注意してください。いずれかのいくつかを追加しcustomerId、あなたの中itemの、またはコメントでblexの提案@てみてください。

ShashanSooriyahetti Dec 06 2020 at 18:56

あなたはこのようなことをすることができます

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

結果

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

ソース デモ