291 votes

Utiliser async await avec Array.map

Étant donné le code suivant :

var arr = [1,2,3,4,5];

var results: number[] = await arr.map(async (item): Promise<number> => {
        await callAsynchronousOperation(item);
        return item + 1;
    });

ce qui produit l'erreur suivante :

TS2322 : Le type 'Promise<number>[]' n'est pas assignable au type 'number[]'. Le type 'Promise<number> n'est pas assignable au type 'number'.

Comment puis-je le réparer ? Comment puis-je faire async await et Array.map travailler ensemble ?

6 votes

Pourquoi essayez-vous de transformer une opération synchrone en une opération asynchrone ? arr.map() est synchrone et ne renvoie pas de promesse.

2 votes

Vous ne pouvez pas envoyer une opération asynchrone à une fonction, comme map qui s'attend à ce qu'il soit synchrone, et s'attendre à ce que cela fonctionne.

2 votes

@jfriend00 J'ai plusieurs instructions await dans la fonction interne. C'est en fait une longue fonction et je l'ai juste simplifiée pour la rendre lisible. J'ai ajouté maintenant un appel await pour rendre plus claire la raison pour laquelle elle doit être asynchrone.

2voto

Vous pouvez utiliser :

for await (let resolvedPromise of arrayOfPromises) {
  console.log(resolvedPromise)
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of

Si vous souhaitez utiliser Promise.all() Vous pouvez plutôt opter pour Promise.allSettled() Ainsi, vous pouvez avoir un meilleur contrôle sur les promesses rejetées.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

2voto

user2491400 Points 55

Une solution utilisant map() de modern-async :

import { map } from 'modern-async'

...
const result = await map(myArray, async (v) => {
    ...
})

L'avantage d'utiliser cette bibliothèque est que vous pouvez contrôler la concurrence à l'aide de mapLimit() ou mapSeries() .

0voto

Victor Muresanu Points 66

J'avais une tâche du côté BE pour trouver toutes les entités d'un repo, et pour ajouter une nouvelle propriété url et retourner à la couche contrôleur. Voici comment je l'ai réalisé (grâce à la réponse d'Ajedi32) :

async findAll(): Promise<ImageResponse[]> {
    const images = await this.imageRepository.find(); // This is an array of type Image (DB entity)
    const host = this.request.get('host');
    const mappedImages = await Promise.all(images.map(image => ({...image, url: `http://${host}/images/${image.id}`}))); // This is an array of type Object
    return plainToClass(ImageResponse, mappedImages); // Result is an array of type ImageResponse
  }

Note : L'image (entité) n'a pas de propriété url, mais ImageResponse - en a une.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X