web-dev-qa-db-fra.com

Utilisez async wait 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 <numéro> []' n'est pas assignable au type 'numéro []'. Le type 'Promise <number> n'est pas assignable au type' number '.

Comment puis-je le réparer? Comment faire en sorte que async await et Array.map fonctionnent ensemble?

129
Alon

Le problème ici est que vous essayez de await un tableau de promesses plutôt qu’une promesse. Cela ne fait pas ce que vous attendez.

Lorsque l'objet transmis à await n'est pas une promesse, await renvoie simplement la valeur telle quelle, au lieu d'essayer de la résoudre. Donc, puisque vous avez passé await un tableau (d'objets Promise) ici au lieu d'une promesse, la valeur renvoyée par wait est simplement ce tableau, qui est de type Promise<number>[].

Ce que vous devez faire ici est d’appeler Promise.all sur le tableau renvoyé par map afin de le convertir en une seule promesse avant awaiting.

Selon le docs MDN pour Promise.all :

La méthode Promise.all(iterable) renvoie une promesse qui est résolue lorsque toutes les promesses de l'argument itérable ont été résolues, ou qu'elles sont rejetées avec le motif de la première promesse passée qui a été rejetée.

Donc dans votre cas:

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;
}));

Cela résoudra l’erreur spécifique que vous rencontrez ici.

291
Ajedi32

Il existe une autre solution si vous n'utilisez pas Promises en natif, mais Bluebird.

Vous pouvez également essayer d'utiliser Promise.map () , en mélangeant les tableaux array.map et Promise.all.

Dans votre cas:

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

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

Si vous mappez sur un tableau de promesses, vous pouvez ensuite les résoudre en un tableau de nombres. Voir Promise.all .

6
Dan Beaulieu

Je vous recommande d'utiliser Promise.all comme indiqué ci-dessus, mais si vous avez vraiment envie d'éviter cette approche, vous pouvez créer une boucle pour ou une autre:

const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr){
  await callAsynchronousOperation(i);
  resultingArr.Push(i + 1)
}
0
Beckster