Attendi le iterazioni array.map in Promise.all [duplicate]
Ho il seguente codice che dovrebbe aggiungere articoli per i clienti se non esistono già. L'esecuzione dovrebbe essere parallela.
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`);
Il problema è che l'esecuzione non è in attesa di createCustomerItemessere risolta nei casi di!productExists)
Questo è il 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 presentdovrebbe venire per ultimo.
Quando tutti gli elementi esistono già, il processo sembra buono.
Risposte
Prova con flatMap:
await Promise.all(
customers.flatMap(async (customer) => {
return customer.items.map(async (item) => {
Invece di restituire un array di array di Promises, appiattirà il contenuto a un semplice array di Promises, che è ciò che ci si Promise.allaspetta.
NB Non è chiaro dalla tua domanda se il raggruppamento di articoli per cliente debba essere conservato. In tal caso, notare che questa soluzione modifica la struttura dei dati in un elenco appiattito, quindi si perde il raggruppamento. O aggiungine un po ' customerIdnei tuoi itemo prova il suggerimento di @ blex nei commenti.
puoi fare qualcosa di simile
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();
risultati
Start
["apple", "grape", "pear"]
End
demo sorgente