J'ai besoin de faire un nombre inconnu d'appels asynchrones en parallèle via Promise.all
. Quelque chose de similaire à ceci:
const [call1, call2, call3] = await Promise.all(externalCalls);
Ensuite, externalCalls
sera transmis à Promise.all
afin qu'ils puissent être exécutés en parallèle. P >
Idéalement, j'aimerais utiliser la déstructuration des résultats pour pouvoir faire référence aux résultats par leur nom, c'est-à-dire
let externalCalls = [call1()]; if (someCondition1) { externalCalls.push(call2()); } if (someCondition2) { externalCalls.push(call3()); }
Je connais call1 code> sera toujours là, mais je ne sais pas si
call2
ou call3
sera là. Je voudrais donc définir le résultat const
de l'appel wait Promise.all
dynamiquement pour avoir les bonnes propriétés, est-ce possible? Ou suis-je coincé avec un tableau de résultats générique de longueur inconnue, puis dois-je inspecter chaque élément des résultats pour voir quel appel l'a produit?
4 Réponses :
il n'y a pas de moyen direct de connaître la source de la réponse de promise.all.
mais vous pouvez ajouter plus d'informations à la réponse de call1, call2, call3
afin que votre code modifié soit ressemble à ça:
returnedData = { 'call1': { call1 related data}, 'call2': { call2 related data}, 'call3': { call3 related data}, }
et dans votre réponse promise.all, vous pouvez vérifier la source de chaque réponse renvoyée comme suit "
let returnedData = {}; Promise.all(externalCalls).then(allData => { for(let data of allData){ returnedData[data.source] = data; console.log(returnedData); } });
Oui, je suis conscient de cette approche, mais ma question portait spécifiquement sur la possibilité de générer dynamiquement l'instruction de déstructuration. Merci!
D'une part, vous savez déjà quels appels ont été .push ()
vers externalCalls
, sur la base de someCondition1
, etc. Mais peut-être est-il préférable de construire externalCalls
d'une manière différente pour qu'il ait toujours la même longueur:
const conditions = [true, someCondition1, etc] const calls = [call1, call2, etc] const externalCalls = conditions.map( (c, i) => c ? calls[i]() : Promise.resolve(null)) const [result1, result2, etc] = await Promise.all(externalCalls)
Si someCondition1 est faux, vous ne poussez rien, alors si someCondition2 est vrai, vous poussez call3 (), donc vous devriez vous attendre à ce que call3 soit dans le deuxième élément du tableau retourné. Par conséquent, à la place, vous pouvez simplement renvoyer undefined pour les appels qui n'ont aucune valeur, en conservant les appels dans le tableau ayant des index synchronisés.
let someCondition1 = false; let someCondition2 = true; let call1 = () => Promise.resolve("hello"); let call2 = () => Promise.resolve("world"); let call3 = () => Promise.resolve(":)"); let externalCalls = [ call1(), someCondition1 ? call2() : undefined, someCondition2 ? call3() : undefined ]; async function resolveCalls(calls){ const [call1, call2, call3] = await Promise.all(calls); console.log("call1:", call1); console.log("call2:", call2); console.log("call3:", call3); } resolveCalls(externalCalls);
Merci @George. Vous et ᆼ ᆺ ᆼ avez tous deux proposé la même approche, mais comme ils vous ont battu de 7 minutes, je vais accepter leur réponse, mais je les ai tous les deux votés. :)
Mon code
const promiseFor1stAPICall = () => { return new Promise((resolve) => { return setTimeout(() => { resolve({ data: "1st api data" }); }, 2000); }); }; const promiseFor2edAPICall = () => { return new Promise((resolve) => { return setTimeout(() => { resolve({ data: "2ed api data" }); }, 2000); }); }; const promiseFor3rdAPICall = () => { return new Promise((resolve) => { return setTimeout(() => { resolve({ data: "3rd api data" }); }, 2000); }); }; const promiseFor4thAPICall = () => { return new Promise((resolve) => { return setTimeout(() => { resolve({ data: "4th api data" }); }, 2000); }); }; async function destructureFromPromiseAll() { const promises = []; promises.length = 4; const obj = { condition1: false, condition2: true, }; promises[0] = promiseFor1stAPICall(); if (obj.condition1) { promises[1] = promiseFor2edAPICall(); promises[2] = promiseFor3rdAPICall(); } if (obj.condition2) { promises[3] = promiseFor4thAPICall(); } const data = await Promise.all(promises); return data; } async function log() { const data = await destructureFromPromiseAll(); const [ firstAPICallRes, secondAPICallRes, thirdAPICallRes, fourthAPICallRes, ] = data; console.log( firstAPICallRes, secondAPICallRes, thirdAPICallRes, fourthAPICallRes ); } log(); ============output=============== {data: '1st api data'}, undefined, undefined, {data: '4th api data'}
const [call1, ... rest]
peut-êtreconst [call1, ... restCalls]
?cela devrait juste fonctionner, mais il est possible que call2, call3 ne soit pas défini.
@ ᆼ ᆺ ᆼ Ouais, donc cela permet un nombre dynamique d'éléments après call1, mais pouvez-vous expliquer comment j'utiliserais ensuite le paramètre rest pour déterminer quels appels ont été effectués?
@George, malheureusement, cela ne fonctionne pas. Disons que j'ai fait call1 et call3, si le résultat const a été défini comme
[call1, call2, call3]
, le résultat de call3 est en fait dans la variablecall2
, et < code> call3 n'est pas défini.Ah je vois, si someCondition1 est faux, vous ne poussez rien, alors si someCondition2 est vrai, vous appuyez sur call3 (), donc vous devriez vous attendre à ce que call3 soit dans le deuxième élément du tableau retourné.
Merci @BrianPloetz pour avoir posé ces questions, c'est exactement ce à quoi je suis confronté.
J'ai posté le code ci-dessous, veuillez regarder