Дождитесь итераций array.map в Promise.all [дубликат]
У меня есть следующий код, который должен добавлять элементы для клиентов, если они еще не существуют. Исполнение должно быть параллельным.
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
должно быть последним.
Когда все элементы уже существуют, процесс выглядит хорошо.
Ответы
Попробуйте flatMap:
await Promise.all(
customers.flatMap(async (customer) => {
return customer.items.map(async (item) => {
Вместо того, чтобы возвращать массив массивов промисов, он сглаживает содержимое до простого массива промисов, чего и Promise.all
ожидает.
NB. Из вашего вопроса не очевидно, нужно ли сохранять группировку товаров по покупателям. Если это так, обратите внимание, что это решение изменяет структуру данных на плоский список, поэтому вы теряете группировку. Либо добавьте customerId
в свой item
s, либо попробуйте предложение @blex в комментариях.
ты можешь сделать что-то вроде этого
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
исходная демонстрация