Inscrivez-vous gratuitement pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter
Vous n'êtes pas encore inscrit sur Developpez.com ?
{"Title": "Translation example",
"Intro": "Hello I am et, I am 500 years old.",
"Startpage": {"TranslationSections": "Hello World",
"TranslationsSubSections" :{"TitleOne" : "Hello All",
"TitleTwo" : "Hello You",
"TitleTree" : "Hello Me"}},
"Aboutpage": {"TranslationSections": "We are letsboot"}}
quand j'essaie de stoker les valeurs de ma promesses dans un tableau
Bon, j’essaye de comprendre la logique de ton code mais je pense qu’il manque des éléments. Je vais essayer de t’aider quand même.
Je reconnais que je ne t’ai pas donné beaucoup d’indications la dernière fois. Promise.all attend en paramètre un tableau d’objets Promise, et renvoie une nouvelle promesse qui est résolue si et seulement si toutes les promesses du tableau sont résolues. Mais voyons ce qui se passe dans ton code :
Tu passes un tableau à Promise.all, mais je ne sais pas ce que renvoie getValues. Cette fonction renvoie-t-elle une promesse ? Un tableau de promesses ? Je pense qu’il y a un niveau de tableau en trop.
Soit getValues renvoie une seule promesse, et dans ce cas tu n’as pas besoin de Promise.all ;
soit elle renvoie déjà un tableau, et dans ce cas tu n’as pas besoin des crochets [ ... ].
Note : si le tableau passé à Promise.all contient autre chose que des promesses, ça va marcher quand même (en tout cas sous Firefox, je viens de tester), et ça va considérer que tu as passé des promesses déjà résolues. Mais c’est un peu « par accident » et je ne crois pas que ce soit une bonne idée de se reposer sur ce comportement.
Je ne sais pas si ça va t’aider, mais j’ai lu récemment un article de blog qui proposait de transformer la fonction setTimeout en quelque chose qui retourne une promesse. Par exemple :
Dans le cas présent, la console affichera un tableau contenant quatre fois undefined, qui s’explique par le fait qu’on avait quatre promesses dans le tableau de départ, et que ces promesses ne se résolvent en aucune valeur.
Tu trouveras peut-être que cet exemple n’était pas très parlant. Prenons un autre cas simple : des promesses qui se résolvent instantanément (mais attention, une promesse se résoud toujours de manière asynchrone !)
Encore une fois, je te laisse l’exercice avec la réponse en spoiler. On veut quelque chose qui se comporte comme ceci :
let promise42 = newPromise((resolve, reject) => {resolve(42); });
On peut corser un tout petit peu les choses en souhaitant quelque chose de plus dynamique : une fonction qui reçoit un paramètre et qui retourne une promesse qui se résoud en ce paramètre.
Un peu plus haut, j’ai rapidement attiré ton attention sur le fait que les promesses se résolvent toujours de façon asynchrone. C’est une manière savante de dire « pas dans l’ordre ». Tu auras sans doute remarqué ce genre de phénomène :
Une autre façon de faire : si tu utilises un return (ou la forme « expression » des fonctions flèches) à l’intérieur d’une fonction .then, tu peux chaîner les .then :
J’ai l’impression que tu as deux variables dans ta fonction mytest qui remplissent le même rôle : valuesArray et translatedArray. À mon avis tu devrais retirer une des deux.
Pour le reste, je pense que tu n’es pas loin d’avoir quelque chose qui marche. Et je crois qu’en fin de compte, tu n’auras pas besoin de Promise.all. En fait, Promise.all pourrait même te poser problème car, vu que tu fais un certain nombre de requêtes réseau, il y a une certaine probabilité qu’au moins une d’entre elles échoue, et donc que Promise.all renvoie un résultat négatif. Malheureusement, il n’existe pas de fonction native Promise.most qui permettrait de ne pas tenir compte des échecs… Cela dit, rien ne nous empêche de la coder nous-mêmes.
Attention aux noms que tu donnes à tes arguments de fonctions. Il y a un manque de cohérence entre cette ligne :
Également, la variable body dans getTranslation n’est pas utilisée à la fin. J’imagine que c’est un oubli.
Un détail à propos de ta fonction récursive : à l’intérieur tu appelles un forEach. Je ne sais pas quelle profondeur peut atteindre ta structure de données, mais j’ai déjà vu certains scripts échouer à cause de la pile d’appels qui était surchargée. Dans ton cas tu peux limiter ce risque en remplaçant la fonction forEach par une boucle for..of combinée à Object.entries :
Il viendrait en dernier si tu n’avais pas demandé un setTimeout d’une seconde… Une seconde c’est énorme en comparaison du temps d’exécution d’une fonction JavaScript moyenne, même récursive. Tu peux t’en rendre compte en plaçant des performance.now() avant et après l’appel à mytest :
functionsendToGoogleTranslate(array, lang){if(array && array.size > 0){let t0 = performance.now();
let myloop = mytest(array, lang);
let t1 = performance.now();
console.log(t1 - t0); // affiche des millisecondesPromise.all(myloop).then(function(promises){
console.log("Arriver en dernier");
});
}}
Je suis à peu près certain que ça t’affichera un nombre qui est largement inférieur à 1000.
Je pense qu’il te manque la compréhension de ce qui est synchrone et ce qui ne l’est pas.
Une résolution de promesse est asynchrone. Une fonction appelée avec setTimeout, setInterval ou requestAnimationFrame est asynchrone. Un gestionnaire d’évènement, ce qui inclut les évènements ajax mais aussi les évènements souris/tactile et clavier, est asynchrone. Un appel récursif, une boucle for ou while, une création d’objet, tout ça est synchrone. Généralement, tout le reste est synchrone, mais il y a peut-être des cas que j’ai oubliés.
Sous les navigateurs actuels, (si on oublie la récente technologie des workers) JavaScript n’a qu’un seul fil (thread) d’exécution. Le code asynchrone est placé en attente, et est exécuté immédiatement dès que le thread est libre.
Imagine une fonction simple contenant uniquement des instructions synchrones :
functionf(){let x = 5;
x = x * 2;
x = x + 1;
Promise.resolve("coucou")
.then(functiong(value){ console.log(value); });
console.log(x);
}
La fonction que nous passons à .then, que j’ai nommée g pour plus de lisibilité, est placée en file d’attente jusqu’à ce que le thread soit libéré. En l’occurence, quand la fonction f() se termine.
On peut voir que, en quelques sortes, un nouveau bloc a été « sorti » du bloc principal. Et on voit bien que la valeur de x (11) va s’afficher avant le « coucou ».
Quand tu utilises setTimeout, un délai est rajouté artificiellement pour retarder l’exécution de la fonction.
Tout ça pour dire que je ne comprends pas pourquoi tu as voulu mettre un setTimeout dans ta promesse. Est-ce que je t’ai induit en erreur avec mes explications précédentes ?
La FAQ JavaScript – Les cours JavaScript Touche F12 = la console → l’outil indispensable pour développer en JavaScript !
Partager