Utilice async await con Array.map

Resuelto Alon asked hace 8 años • 10 respuestas

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 awaity Array.maptrabajar juntos?

Alon avatar Oct 20 '16 02:10 Alon
Aceptado

El problema aquí es que está intentando realizar awaituna serie de promesas en lugar de una Promesa. Esto no hace lo que esperas.

Cuando el objeto pasado awaitno es una Promesa, awaitsimplemente devuelve el valor tal como está inmediatamente en lugar de intentar resolverlo. Entonces, dado que pasó awaituna 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.alla la matriz devuelta por mappara convertirla en una sola Promesa antes de awaitejecutarla.

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.anyo Promise.raceen lugar de Promise.all, aunque en la mayoría de las situaciones (casi con seguridad incluida esta) Promise.allserá la que desee.

Ajedi32 avatar Oct 19 '2016 20:10 Ajedi32

Esta es la forma más sencilla de hacerlo.

await Promise.all(
    arr.map(async (element) => {
        ....
    })
)
ajitspyd avatar Apr 22 '2022 14:04 ajitspyd

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;
  });
Gabriel Cheung avatar Oct 11 '2017 10:10 Gabriel Cheung

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

Abhijeet Narvekar avatar Jan 03 '2021 16:01 Abhijeet Narvekar