web-dev-qa-db-fra.com

Comment faire promise.all pour un tableau de tableau de promesses?

J'essaie d'exécuter un tableau de fonctions en parallèle et quand tout le monde a terminé, je veux travailler sur ce résultat. J'utilise des promesses. Maintenant, je peux mettre toutes les fonctions dans un tableau et faire Promise.all (tableau de fonctions) Mais j'ai un tableau comme

[[promise1, promise2], [promise3,promise4], [promise5,promise6]],

où chaque promesse est fonction promis. Le document de référence Promise indique que le paramètre dans Promise.all doit être un objet itérable et mon tableau est itérable. Mais ça ne marche pas pour moi. Je pense qu'il exécute [promesse1, promesse2] comme une promesse mais pas une promesse individuelle.

Quelqu'un peut-il m'aider, comment je peux y parvenir ou existe-t-il une meilleure façon?

18
Rohit Vyavahare

Vous devez également appeler Promise.all Pour chaque élément du tableau:

const promise4all = Promise.all(
   promiseArray.map(function(innerPromiseArray) {
        return Promise.all(innerPromiseArray);
   })
);

Ou directement:

// Fix: Promise.all.bind is required because it seems like Promise.all
// implementation relies on "this"
const promise4All = Promise.all(promiseArray.map(Promise.all.bind(Promise)))
// or
// const promise4All = Promise.all(promiseArray.map(p => Promise.all(p)))

De cette façon, le Promise.all Externe obtient les promesses groupées dans d'autres Promise.all:

promise4all.then(function(promiseGroupResult) {
  // promiseGroupResult is the actual result of each promise group
  // and you'll be able to get each result this way: promiseGroupResult.somePropertyName
});
23

Vous pouvez simplement utiliser Promise.all sur tous les tableaux internes, puis sur le tableau externe, pour obtenir une promesse pour le tableau de tableaux:

Promise.all(promiseArrArr.map(Promise.all, Promise)).then(arrArr => …)

Remarquerez que Promise.all prend un tableau de promesses, pas un tableau de fonctions renvoyant des promesses.

8
Bergi

Une autre option consiste à aplatir votre tableau de tableaux en un seul tableau sur lequel vous pouvez ensuite utiliser Promise.all() directement. Directement à partir d'un exemple sur MDN , vous pouvez le faire comme ceci en utilisant .reduce() et .concat():

var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];

Promise.all(promises.reduce(function(a, b) { return a.concat(b); }, []))
  .then(function(results) {
    // all done here
    // results are in a flattened array
});

Cette solution permet au tableau de promesses d'origine de contenir des promesses individuelles ou des tableaux de promesses ou toute combinaison des deux. Il est flexible de cette manière et fournit les résultats dans un seul tableau aplati de résultats qui sont dans le même ordre que les promesses d'origine, mais sont aplatis dans un seul tableau. Parce que Promise.all() nécessite que vous lui passiez un tableau, les autres solutions présentées ici nécessitent que l'entrée soit un tableau strict de tableaux - ce tableau ne peut pas avoir de promesses simples en lui uniquement des tableaux de promesses. Cette solution est plus flexible de cette manière et accepte les deux types d'entrée.

Par exemple, cela fonctionnera très bien si l'entrée se trouve être comme ceci:

var promises = [promise1, promise2, [promise3, promise4], [promise5, promise6]];

Voir la démonstration de travail: https://jsfiddle.net/jfriend00/dLsktyyn/


Ou vous pourriez trouver utile d'avoir la fonction flatten() qui traîne pour d'autres utilisations:

function flatten(arr) {
    return arr.reduce(function(a, b) { return a.concat(b); }, []);
}

var promises = [[promise1, promise2], [promise3,promise4], [promise5,promise6]];

Promise.all(flatten(promises)).then(function(results) {
    // all done here
});    
5
jfriend00

Si vous avez un nombre fixe de sous-réseaux, je vous suggère d'utiliser cette solution simple:

const balancePromises = [...];
const symbolPromises = [...];

const [balances, symbols] = await Promise.all([
    Promise.all(balancePromises),
    Promise.all(symbolPromises)
]);

Plusieurs promesses pourraient également être mises en parallèle comme ceci:

const [
    balances,
    debt,
    name,
] = await Promise.all([
    this.contract.getBalanceOf(user),
    this.contract.getDebtOf(user),
    this.contract.getNameOf(user),
]);
3
k06a

Vous pouvez utiliser cette approche:

var promisesArray = [
    [promise1, promise2],
    [promise3,promise4],
    [promise5,promise6]
].reduce(function (arr, item) {
    item.forEach(function (promise) {
       arr.Push(promise);
    });
    return arr;
}, []);
Promise.all(promisesArray).then(function () {
    // code
});
0
Dmitriy