Gestion de promise avec une boucle
RésoluGuttcanard Messages postés 28 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
Je tourne en rond sur un problème :
J'ai un tableau d'objet, pour chaque objet, si une propriété existe, alors je dois faire un traitement qui demande un peu de temps (téléchargement de fichier) et rajoute a un object le résultat du téléchargement.
En gros, je veux boucler mon tableau d'objet, attendre que tous les traitements soient terminés et récupérer l'object résultat.
Or, quand je passe à la procédure suivante, le résultat est indéfini.
A force de tourner en rond, je ne vois plus de solutions...
async function traitement(el) { dejaFait = [] if (!dejaFait.includes(el.id)) { dejaFait.push(el.id); inlineFile = await downloadSections(el.id.toString()) .then((list) => { resultat = concatResult(resultat, Object.values(list.features)) }) } return resultat } function test() { Promise.all(tablo.map(async (el) => { if (el.propriété) { await traitement(el) } })) .then((resultat) => actionSuivante(resultat)) }
- Gestion de promise avec une boucle
- Logiciel gestion locative gratuit excel - Télécharger - Comptabilité & Facturation
- Gestion de fichiers - Télécharger - Gestion de fichiers
- Logiciel gestion photo gratuit - Guide
- Gestion autorisation application android - Guide
- Logiciel gestion cabinet médical gratuit - Télécharger - Organisation
2 réponses
Wouaw ça c'est du costaud !
Un super grand merci pour toutes ces explications : elles comblent mes manques en matière de promesses (je suis auto-ditacte).
Je vais essayer de me débrouiller sans l'alternative proposée (je préfère apprendre en faisant) mais merci beaucoup pour tout !
Bonjour,
Ton problème vient probablement du fait que la gestion des promesses et du résultat dans ton code n'est pas tout à fait correcte, ce qui entraîne un undefined ou des comportements inattendus.
Variable resultat non définie ou mal gérée :
Dans traitement, la variable resultat semble être une variable globale ou non initialisée. Si elle n'est pas correctement initialisée, elle peut causer des erreurs ou retourner undefined.
De plus, resultat est modifié dans le .then de downloadSections, mais la fonction traitement retourne resultat avant que la promesse ne soit résolue.
Utilisation de dejaFait :
La variable dejaFait semble être utilisée pour éviter les duplications, mais elle est définie à l'intérieur de traitement. Cela signifie qu'à chaque appel de traitement, elle est réinitialisée à [], ce qui rend son utilisation inefficace. Elle devrait être définie en dehors de la fonction si tu veux qu'elle persiste entre les appels.
Structure de Promise.all :
Dans test, tu utilises Promise.all sur tablo.map, mais tu ne retournes rien explicitement dans le map lorsque el.propriété est faux. Cela peut entraîner un tableau de promesses contenant des undefined, ce qui peut causer des problèmes dans actionSuivante.
Retour de traitement :
La fonction traitement retourne resultat, mais comme resultat est modifié dans un .then, il est possible que la fonction retourne resultat avant que la promesse ne soit résolue.
Voici une version corrigée de ton code, avec des explications pour chaque amélioration :
// Définir dejaFait et resultat en dehors de la fonction pour éviter la réinitialisation let dejaFait = []; let resultat = []; // Initialisation explicite de resultat comme un tableau async function traitement(el) { // Vérifier si l'élément a déjà été traité if (!dejaFait.includes(el.id)) { dejaFait.push(el.id); // Ajouter l'ID à dejaFait const list = await downloadSections(el.id.toString()); // Attendre le téléchargement resultat = concatResult(resultat, Object.values(list.features)); // Mettre à jour resultat } return resultat; // Retourner resultat } async function test(tablo) { // Utiliser Promise.all pour traiter les éléments en parallèle const promises = tablo.map(async (el) => { if (el.propriété) { return await traitement(el); // Retourner explicitement le résultat } return null; // Retourner null si l'élément ne doit pas être traité }); const results = await Promise.all(promises); // Attendre la résolution de toutes les promesses const filteredResults = results.filter((res) => res !== null); // Filtrer les null const finalResult = filteredResults[filteredResults.length - 1] || []; // Prendre le dernier résultat non-null ou un tableau vide actionSuivante(finalResult); // Appeler actionSuivante avec le résultat final }
Points à vérifier :
Fonction concatResult : Assure-toi que cette fonction est correctement définie et qu'elle retourne un tableau mis à jour. Si elle ne fonctionne pas comme prévu, cela pourrait aussi causer des problèmes.
Fonction downloadSections : Vérifie que cette fonction retourne bien une promesse qui résout un objet avec une propriété features.
Comportement attendu de resultat : Si tu veux que chaque appel à traitement retourne un résultat indépendant (plutôt qu'un tableau global), tu peux modifier traitement pour retourner uniquement le résultat de l'élément traité, et collecter ces résultats dans test.
Exemple d'appel :
const tablo = [ { id: 1, propriété: true }, { id: 2, propriété: false }, { id: 3, propriété: true } ]; test(tablo);
Alternative si tu veux des résultats indépendants :
Si tu veux que chaque élément traité retourne son propre résultat (plutôt qu'un tableau global), voici une version modifiée :
let dejaFait = []; async function traitement(el) { if (!dejaFait.includes(el.id)) { dejaFait.push(el.id); const list = await downloadSections(el.id.toString()); return Object.values(list.features); // Retourner uniquement les features de cet élément } return []; // Retourner un tableau vide si déjà traité } async function test(tablo) { const promises = tablo.map(async (el) => { if (el.propriété) { return await traitement(el); } return []; }); const results = await Promise.all(promises); const finalResult = results.flat(); // Aplatir les résultats en un seul tableau actionSuivante(finalResult); }
Cette version retourne un tableau contenant tous les features des éléments traités, sans utiliser une variable globale resultat.