Использование async/await с методом Array.map
Столкнулся с проблемой при работе с асинхронными функциями в TypeScript. У меня есть следующий код:
var arr = [1, 2, 3, 4, 5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
Этот код вызывает ошибку компиляции:
TS2322: Type 'Promise<number>[]' is not assignable to type 'number[]'.
Type 'Promise<number>' is not assignable to type 'number'.
Я пытаюсь использовать async/await
вместе с Array.map
, но не могу понять, как правильно это сделать. Как я могу исправить эту ошибку? Как объединить async/await
и Array.map
?
4 ответ(ов)
Самый простой способ сделать это:
await Promise.all(
arr.map(async (element) => {
....
})
)
Этот код позволяет одновременно обрабатывать каждый элемент массива arr
с помощью асинхронной функции. Использование Promise.all
обеспечивает выполнение всех промисов и дожидается их завершения, прежде чем продолжить выполнение дальнейшего кода.
Вы можете использовать следующий код для итерации по массиву промисов и ожидания их разрешения:
for await (let resolvedPromise of arrayOfPromises) {
console.log(resolvedPromise);
}
Дополнительную информацию можно найти в документации Mozilla.
Если вы предпочитаете использовать Promise.all()
, вы можете рассмотреть вариант с Promise.allSettled()
, который предоставляет более эффективный контроль над отклонёнными промисами. Это позволяет обрабатывать результаты всех промисов, независимо от того, были ли они выполнены успешно или нет.
Дополнительную информацию о Promise.allSettled()
можно найти в документации Mozilla.
Я бы порекомендовал использовать Promise.all
, как упоминалось выше, но если вы действительно хотите избежать этого подхода, вы можете использовать цикл for
или любой другой цикл:
const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr) {
await callAsynchronousOperation(i);
resultingArr.push(i + 1);
}
Для вашего сведения: Если вы хотите проходить по элементам массива, а не по его индексам (как отметил @ralfoide в комментарии), используйте of
вместо in
в операторе let i in arr
. Так будет правильнее:
for (let i of arr) {
await callAsynchronousOperation(i);
resultingArr.push(i + 1);
}
Вы можете реализовать задачу на стороне бэкенда следующим образом. Вам нужно получить все сущности из репозитория, добавить новое свойство url
и вернуть результат на слой контроллера. Вот пример кода, который демонстрирует, как это можно сделать (благодаря ответу Ajedi32):
async findAll(): Promise<ImageResponse[]> {
const images = await this.imageRepository.find(); // Это массив типа Image (сущность из базы данных)
const host = this.request.get('host');
const mappedImages = await Promise.all(images.map(image => ({...image, url: `http://${host}/images/${image.id}`}))); // Это массив типа Object
return plainToClass(ImageResponse, mappedImages); // Результат - массив типа ImageResponse
}
Примечание: Сущность Image
не имеет свойства url
, но ImageResponse
- да.
Использование async/await с циклом forEach
Синтаксис асинхронной стрелочной функции
Сочетание асинхронной функции, await и setTimeout
Переопределение типа свойства интерфейса, определённого в файле d.ts TypeScript
Как проверить, содержит ли массив строку в TypeScript?