Utilice async await con Array.map
Dado el siguiente código:
var arr = [1,2,3,4,5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
lo que produce el siguiente error:
TS2322: El tipo 'Promesa<número>[]' no se puede asignar al tipo 'número[]'. El tipo 'Promesa<número> no se puede asignar al tipo 'número'.
¿Cómo puedo arreglarlo? ¿ Cómo puedo hacer async await
y Array.map
trabajar juntos?
El problema aquí es que está intentando realizar await
una serie de promesas en lugar de una Promesa. Esto no hace lo que esperas.
Cuando el objeto pasado await
no es una Promesa, await
simplemente devuelve el valor tal como está inmediatamente en lugar de intentar resolverlo. Entonces, dado que pasó await
una matriz (de objetos Promise) aquí en lugar de una Promesa, el valor devuelto por await es simplemente esa matriz, que es de tipo Promise<number>[]
.
Lo que probablemente quieras hacer es llamar Promise.all
a la matriz devuelta por map
para convertirla en una sola Promesa antes de await
ejecutarla.
Según los documentos de MDN paraPromise.all
:
El
Promise.all(iterable)
método devuelve una promesa que se resuelve cuando todas las promesas en el argumento iterable se han resuelto, o se rechaza con el motivo de la primera promesa pasada que se rechaza.
Entonces en tu caso:
var arr = [1, 2, 3, 4, 5];
var results: number[] = await Promise.all(arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
}));
Esto resolverá el error específico que encuentra aquí.
Dependiendo exactamente de lo que esté intentando hacer, también puede considerar usar Promise.allSettled
, Promise.any
o Promise.race
en lugar de Promise.all
, aunque en la mayoría de las situaciones (casi con seguridad incluida esta) Promise.all
será la que desee.
Esta es la forma más sencilla de hacerlo.
await Promise.all(
arr.map(async (element) => {
....
})
)
Hay otra solución si no estás utilizando Promises nativas sino Bluebird.
También puedes intentar usar Promise.map() , mezclando array.map y Promise.all
En tu caso:
var arr = [1,2,3,4,5];
var results: number[] = await Promise.map(arr, async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
Puedes usar:
for await (let resolvedPromise of arrayOfPromises) {
console.log(resolvedPromise)
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of
Si desea utilizarlo Promise.all()
, puede optar por Promise.allSettled()
Así podrá tener un mejor control sobre las promesas rechazadas.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled