jQuery Ajax afficher une très longue liste, ALgo difficile à pondre |
Bienvenue invité ( Connexion | Inscription )
jQuery Ajax afficher une très longue liste, ALgo difficile à pondre |
12 May 2015, 00:43
Message
#1
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
J’ai, sur un serveur, plusieurs très longues listes d’objets (un inventaire à la Prévert) à afficher.
Pour des questions de réactivité , j’en passe par plusieurs requêtes Ajax : L’idée c’est de commencer à afficher les 12 premiers éléments d’une des listes sur une page. Puis ensuite de la compléter la liste sur la page en tache de fond. Comme ca l’internaute n’a pas à attendre que les 12milliards de lignes soient transférées depuis le serveur pour commencer à contempler cette fichue liste. Comme cette liste est trop longue pour entrer dans une seule réponse Ajax, je suis obligé de faire passer ces lignes 12 par douze, jusqu'à épuisement de la liste. J’ignore aussi les tailles exactes de ces listes, celles-ci pouvant évoluer au gré de fantaisies insoupçonnables. Donc, j’ignore combien de douzaines devront transiter, et je compte sur les retours de chaque douzaine pour indiquer si celle-ci est la dernière ou non. Pour couronner le tout, l’internaute peut très bien vouloir décider de visualiser une autre liste, même si la liste en cours d’affichage n’est pas achevée de traiter. J’ai un peu défriché l’algorithme à mettre en place. Pour chaque liste j’utilise un ID différent, et je demande au serveur de me renvoyer systématiquement cet ID pour le comparer à l’ID courant. Comme ca, si l’internaute change de liste, le traitement d’affichage d’une liste avec un ID différent est annulé. La ou je coince, c’est que je me retrouve avec plusieurs requêtes Ajax à envoyer l’une après l’autre, et qui sont de part leur nature Asynchrone. Je ne peux envoyer une requête que si la requête précédente est entièrement traitée, et accessoirement qu’elle indique bien que la liste n’es pas achevée… Dans la panoplie des fonctions jQuery j’ai zieuté des trucs autour des fonctions deferred, mais sincèrement, j’ai du mal à y voir clair. J’ai aussi l’impression que je vais avoir à mettre en place du récursif, alors que j’aurai préféré une boucle… Mais quelque soit la soluce que vous pouvez me donner, je prends ; mes neurones font des nœuds avec cette histoire. Ce message a été modifié par No6 - 12 May 2015, 00:50. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
12 May 2015, 06:14
Message
#2
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Salut No6,
Je n'ai rien de concret à te proposer mais seulement du "carburant pour la pensée". Il existe une initiative faisant partie du manifeste réactif intitulé "reactive streams", il y a des bases et des principes, mais peu de code concret, bien que l'api cliente en Js fasse aussi partie du design. Les présentations peuvent t'inspirer de nouvelles directions de recherche. Bonjour chez toi, J-P Ce message a été modifié par Jaypee - 12 May 2015, 06:15. |
|
|
12 May 2015, 06:50
Message
#3
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 4 969 Inscrit : 26 Jan 2011 Lieu : Pollachius virens Membre no 164 083 |
Salut,
Tu peux aussi t'inspirer du "lazy loading" utilisé pour les images, et ne récupérer les éléments que si l'utilisateur fait défiler la page https://github.com/tuupola/jquery_lazyload Edit : je ne sais pas ce qu'il y a dans ta liste, mais 12 éléments ça me semble très faible pour être trop volumineux pour ajax. Tu récupères tes éléments en JSON ? Ce message a été modifié par yponomeute - 12 May 2015, 06:55. -------------------- MBP 2017 15" avec clavier pourri et touchbar inutile
|
|
|
12 May 2015, 08:59
Message
#4
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Nous sommes tous sur la même ligne, mais il est difficile de traiter ce problème "à l'unilatérale", il faut une archi client (JS) et serveur (Java EE ou .Net)
Et il est question d'un système d'événements, pour que le serveur réagisse aux clients, et les clients au serveur. Les streams (flux) ne sont pas des collections (liste, ensemble...) mais davantage des itérateurs. La différence est la "paresse", les actions réelles sont remises à plus tard, là où on va effectivement utiliser la donnée extraite du stream. On peut imaginer un grand tableau et un stream permettant de le parcourir et un algo de tri. Le retour de la fonction de tri est immédiate. Seule la logique est analysée et transformée en code. C'est seulement au moment où on veut afficher les data que le code est mis en branle pour fournir le résultat effectif. Ces slides dressent le décor : http://www.slideshare.net/rolandkuhn/reactive-streams Celà reste ambitieux, et à la pointe des technos actuelles. J-P |
|
|
12 May 2015, 11:21
Message
#5
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Merci,
Je commence juste à regarder vos réponses. C'est du classique Serveur PHP et les messages sont en JSON. c'est coté Client (Js / jQuery ) que je coince, sur la partie requête Ajax, promise, deferred, etc.. Et sinon 12 éléments c'est juste pour l'exemple, je regarderai par la suite jusqu'où je peux monter, tout en gardant une certaine fluidité Je vous tiens informé de mes évolutions.. Ce message a été modifié par No6 - 12 May 2015, 11:22. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
12 May 2015, 15:37
Message
#6
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 4 969 Inscrit : 26 Jan 2011 Lieu : Pollachius virens Membre no 164 083 |
Un article qui peut t’intéresser : http://josh.zeigler.us/technology/web-deve...o-big-for-json/
-------------------- MBP 2017 15" avec clavier pourri et touchbar inutile
|
|
|
12 May 2015, 15:39
Message
#7
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Tu trouveras sans doute une piste sérieuse avec Rx.js (il existe aussi un Rx.php)
https://github.com/Reactive-Extensions/RxJS J-P |
|
|
12 May 2015, 20:38
Message
#8
|
|
Adepte de Macbidouille Groupe : Membres Messages : 143 Inscrit : 4 Dec 2013 Membre no 188 132 |
On est effectivement dans un problème de stream et de priorités temps réel. Ne maitrisant pas suffisamment les dessous d'Ajax, ni comment le navigateur gère le multi-tâche , je me concentrerai sur le besoin "métier"; on peut essayer d'analyser le comportement et l'attente de l'utilisateur et essayer d'anticiper les actions les plus probables : consulter la page suivante de la même liste, consulter une autre liste liée à la liste courante, revenir en arrière. Quel volume de données et temps de consultation sans besoin de recharger ?
Une piste :
-------------------- Macmini6,2 - Mavrik
|
|
|
13 May 2015, 00:25
Message
#9
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Bon, ben voila ou j'en suis, evidement je coince toujours au même endroit...
Le code HTML : CODE <!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title>Test lecture de Listes</title> <link rel="stylesheet" href="assets/css/testLists.css" /> </head> <body> <header> <h3>Liste Barbie</h3> <span>...</span> <button value="Barbie" disabled="disabled">Liste Barbie</button> <button value="Ken">Liste Ken</button> <button value="Godzilla">Liste Godzilla</button> </header> <section> <!-- ici la liste--> </section> <script src="assets/js/jquery-2.1.4.min.js"></script> <script src="assets/js/testLists.js"></script> </body> </html> La partie css "assets/css/testLists.css" Code @charset "UTF-8"; body { font-family: sans-serif; width: 740px; margin: 20px auto; background-color: #23232e; font-size: 16px; } header { width: 100%; overflow: auto; margin: 10px 0; } header h3 { width: 300px; float: left; padding: 20px 0 0 0; color: wheat;} header span { width: 320px; float: left; margin: 50px 0 0 0; height: 40px; color:aquamarine; font-size: .8em; } header button { width: 120px; height: 30px; font-weight: bold; } section { width: 100%; height: 500px; overflow: auto; } article { width: 90%; margin: 5px; padding: 5px; background-color:cornflowerblue; color:black; display: none;} Tout de suite la partie PHP 'assets/php/RespLists.php' CODE <?php mb_internal_encoding("UTF-8"); // listes à afficher : "nom de la liste" => nombre d'éléments constituants. // juste pour exemple, en substitut d'appel de données depuis un SGBD... $Listes["Barbie"] = 45; $Listes["Ken"] = 26; $Listes["Godzilla"] = 458; $Ref_UI = (isSet($_POST['Ref_UI'])) ? $_POST['Ref_UI'] : 0; // Valeur référence (à retourner) $NomListe = (isSet($_POST['NomListe'])) ? $_POST['NomListe'] : 'Barbie'; // nom de la liste $NoElemRef = (isSet($_POST['NoElemRef'])) ? $_POST['NoElemRef'] : 0; // No du dernier élément affiché $maxElems = (isSet($_POST['maxElems'])) ? $_POST['maxElems'] : 12; // nombre d'élements à renvoyer $ListStatus = 'en cours...'; // vs 'finish' quand toute la liste est lue. $MaxList = $Listes[$NomListe]; $noItem = $NoElemRef; $T_Lignes = array(); for($i = 0; $i < $maxElems ; $i++) { $noItem++; if ($noItem > $MaxList ) { $ListStatus = 'finish'; break; } else { $T_Lignes[] = $NomListe.' élément n° '.$noItem; $NoElemRef = $noItem; } } $T_Repons["Ref_UI"] = $Ref_UI; $T_Repons["ListStatus"] = $ListStatus; $T_Repons["NoElemRef"] = $NoElemRef; $T_Repons["ListElems"] = $T_Lignes; header('Content-type: application/json'); echo json_encode($T_Repons); exit(0); ?> Et la partie JavaScript "assets/js/testLists.js" CODE $(document).ready(function () { var gUI_Ref = 0, gWaveRef = 0, gWaveNb = 10, gListDone = true; $ListBox = $('section'); $('button').on('click', function() { $('header h3').text( $(this).text() ); $('header span').text( 'En cours...' ); $('button').removeAttr('disabled'); $(this).attr('disabled','disabled'); BIBI( $(this).val() ); }); alert('étape1'); // BIBI('Barbie'); function BIBI(NomDeList) { gUI_Ref++; gListAgain = true; inUI_Ref = gUI_Ref; gWaveRef = 0; $ListBox.empty(); alert('étape2'); do { $.when(LoadList (NomDeList, inUI_Ref, gWaveRef )).done( function() { alert('étapeN++'); }); } while ((gListAgain) && (inUI_Ref == gUI_Ref)); } function LoadList (zListName, zUI_Ref, elm_Ref ) { return $.Deferred(function(dfd) { Call_Args = { Ref_UI : zUI_Ref, // Valeur référence? pour chainer les listes. NomListe : zListName, // nom de la liste NoElemRef : elm_Ref, // No du dernier élément affiché maxElems : gWaveNb // nombre d'élements à renvoyer }; $.ajax({ url : 'assets/php/RespLists.php', type : 'POST', data : Call_Args, cache : false, dataType : 'json', error : function(request, error) { alert("Erreur : responseText: "+request.responseText); }, success : function(data) { if (data['Ref_UI'] == gUI_Ref) { gWaveRef = data['NoElemRef']; gListAgain = (data['ListStatus'] != 'finish'); for(var i = 0; i < data['ListElems'].length; i++) { $el = $('<article>').text(data['ListElems'][i]); $el.appendTo($ListBox).delay(100*i).fadeIn(500, dfd.resolve); } } else dfd.resolve; } }); }).promise(); } /******************************************************************************** ********************** // pour tester directement... Call_Args = { Ref_UI : gUI_Ref, // Valeur référence? pour chainer les listes. NomListe : 'Barbie', // nom de la liste NoElemRef : 0, // No du dernier élément affiché maxElems : gWaveNb // nombre d'élements à renvoyer }; $.ajax({ url : 'assets/php/RespLists.php', type : 'POST', data : Call_Args, cache : false, dataType : 'json', error : function(request, error) { alert("Erreur : responseText: "+request.responseText); }, success : function(data) { for(var i = 0; i < data['ListElems'].length; i++) { $el = $('<article>').text(data['ListElems'][i]); $el.appendTo($ListBox).delay(100*i).fadeIn(500); } } }); ******************************************************************************** *****************************/ }); // --> $(document).ready( bien sur, il part dans les choux, je peux même pas ouvrir un débugger ! Je fais vraiment un blocage mental sur ces notions assynchrones, je comprends pas pour quoi, j'en comprends les grands principes, mais je vois pas comment utiliser leurs fonctions! Ce soir relaxation, et demain grand bol d'air! Ce message a été modifié par No6 - 13 May 2015, 01:14. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
13 May 2015, 00:59
Message
#10
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
En tous cas vraiment merci a tous de vous interresser à mon histoire, ça réchauffe le coeur.
@ Jaypee RxJS pourrait certainement être utile, mais ça fait un peu peur, ça fait un gros morceau à digérer... @ yponomeute effectivement, et je ne pensais pas qu'on pouvait atteindre (dans certains cas) le GigaOctet d'info dans une requête Ajax... Mais ce qui est le plus intéressant et significatif (à mon avis) c'est de voir la dégradation des temps de réponses..! @ macpacher évidement, ce serai plus simple si je pouvais en passer par une pagination (ou attaquer ce probleme sous un autre angle), mais sur ce cas présent, les listes ont pour vocation d'être affichées dans leur intégralité. même si au bout du compte cela risque de faire un truc indigeste à lire. D'ailleurs, c'est un peu le but, car cette réalisation permettra par la suite de réorganiser l'info, par touches successives, jusqu'a avoir des "listes cohérentes" Sinon ces listes sont au moins affichées en ordre alphabétique, et sont remplies de Tags et d'ensembles de listes (qui peuvent permettre à leur tour de consulter une nouvelle liste basée sur les tags choisis) D'une certaine manière il n'y a qu'une seule liste, la première est basé sur l'ensemble principal, puis ensuite on navigue à l'intérieur, un peu comme dans un système de fichiers, mais avec des tags hiérachisés en plus. Il y a aussi d'autres trucs, mais c'est déjà compliqué à expliquer, alors j'ai pris l'exemple des listes pour rester plus simple.... ___ ____ ___ Sinon, j'ai trouvé ça sur la toile, mais je vois pas trop comment je pourrai m'en servir ? https://css-tricks.com/multiple-simultaneou...allback-jquery/ -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
13 May 2015, 08:45
Message
#11
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Note annexe: Les exemples de codes PHP montrent une vulnérailité à une attaque par injection de code JS.
Dans le champ NomListe, si tu entres : Barbie';alert('Coucou !');// Il y a des chances que l'alerte (ou n'importe quel code JS mal-intentionné), s'éxécute. J-P |
|
|
13 May 2015, 11:44
Message
#12
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Note annexe: Les exemples de codes PHP montrent une vulnérailité à une attaque par injection de code JS. Dans le champ NomListe, si tu entres : Barbie';alert('Coucou !');// Il y a des chances que l'alerte (ou n'importe quel code JS mal-intentionné), s'éxécute. J-P Bien vu, je fais pas assez attention à ce genre de truc, mais celui-la, je m'en rappellerai. mais, dans le cas présent le code PHP, n'est la qu'en exemple; pour le vrai, avec l'accès sur le SGBD, ce sera un peu plus "blindé". Sinon, je m'oriente vers ue solution récursive, la requête Ajax ne fait pas 10.000 trucs, alors c'est pas vraiment la mer à boire... -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
13 May 2015, 12:36
Message
#13
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Bon, ben finalement, le récursif fonctionne très bien, alors je fais avec.
mais j'aurai bien aimé comprendre le système " deferred " de jQuery.... un jour?? Pour ceux que cela intéresse voici le code retenu, seule la partie JS à changé : CODE $(document).ready(function () {
var gUI_Ref = 0, gWaveNb = 10, // nombre d'élements à renvoyer à la suite par req Ajax.. $ListBox = $('section'); $('button').on('click', function() { $('header h3').text( $(this).text() ); $('header span').text( 'En cours...' ); $('button').removeAttr('disabled'); $(this).attr('disabled','disabled'); AfficherListe( $(this).val() ); }); AfficherListe('Barbie'); // faut bien commencer avec une premiere liste, alors honnnneur aux filles... function AfficherListe (NomListe) { gUI_Ref++; var zUI_Ref = gUI_Ref; RunListe (NomListe, gUI_Ref, 0, gWaveNb); } function RunListe(xNomListe, xUI_Ref, lastElemNo, maxElemNb) { Call_Args = { Ref_UI : xUI_Ref, // Valeur référence? pour chainer les listes. NomListe : xNomListe, // nom de la liste NoElemRef : lastElemNo, // No du dernier élément affiché maxElems : maxElemNb // nombre d'élements à renvoyer }; $.ajax({ url : 'assets/php/RespLists.php', type : 'POST', data : Call_Args, cache : false, dataType : 'json', error : function(request, error) { alert("Erreur : responseText: "+request.responseText); }, success : function(data) { if (xUI_Ref == gUI_Ref) { if (lastElemNo == 0) $ListBox.empty(); for(var i = 0; i < data['ListElems'].length; i++) { $el = $('<article>').text(data['ListElems'][i]); $el.appendTo($ListBox).delay(100*i).fadeIn(500); } if (data['ListStatus'] != 'finish') RunListe (xNomListe, xUI_Ref, data['NoElemRef'], maxElemNb); // récursif, que les Dieux de Cobol nous protègent ! else $('header span').text( 'Liste complétée !' ); } } }); } }); // --> $(document).ready( -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
13 May 2015, 13:30
Message
#14
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
Une autre option qu'il ne faut pas négliger si les listes sont statiques: tout charger en mémoire dans une hash map géante.
Même si ça prend 1 ou 2 Go de mémoire, on peut plus facilement se le permettre de nos jours. Mais il faut aussi trouver un système de cache distribué pour permettre à chaque serveur d'être en phase pou rle contenu. Donc la bd n'est plus qu'un réservoir, lue une fois au démarrage d'un des serveur, puis le cache prend le relais et met à jour tous les noeuds. J-P Ce message a été modifié par Jaypee - 13 May 2015, 13:31. |
|
|
13 May 2015, 14:00
Message
#15
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Ouais..
Faudra que je réfléchisse à cette problématique de cache, ça pourrait s'avérer très payant ! L'autre partie du projet, c'est qu'il est amené à fonctionner en partage, et j'ai toute une gestion concurrente à développer aussi.... Mais je lâche pas l'affaire, je suis loin de me satisfaire d'un appel récursif dans mon code. En attendant je vais au moins ajouter un compteur pour limiter la profondeur des appels, histoire de ne pas exploser la stack. quitte à mettre u nbouton de reprise, voir aussi de pause.... En tout cas, c'est sur, faut que je potasse sérieusement l'aventures des requêtes asynchrone en jQuery. Je corrigerai le code posté ici, avec les dernières corrections... Ce message a été modifié par No6 - 13 May 2015, 14:02. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
13 May 2015, 18:00
Message
#16
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
C'est encore moi,
c'est idiot, mais j'ai trouvé un meilleur moyen pour éviter de remplir la stack des appels récursifs... J'ai juste remplacé l'appel : Code if (data['ListStatus'] != 'finish') par :RunListe (xNomListe, xUI_Ref, data['NoElemRef'], maxElemNb); else..... Code if (data['ListStatus'] != 'finish') window.setTimeout( RunListe, .... Grosse ruse de Sioux... du coup, je peux même envisager l'économie d'un appel Ajax, en vérifiant avant que je suis sur le même xUI_Ref... code final... CODE $(document).ready(function () {
var gUI_Ref = 0, // globale servant de N° de référence sur la liste en cours gWaveNb = 10, // nombre d'élements à renvoyer à la suite par req Ajax.. $ListBox = $('section'); $MsgBox = $('header span'); AfficherListe('Barbie'); // faut bien commencer avec une premiere liste, alors honnnneur aux filles... $('button').on('click', function() { $MsgBox.text( 'En cours...' ); $('header h3').text( $(this).text() ); $('button').removeAttr('disabled'); $(this).attr('disabled','disabled'); AfficherListe( $(this).val() ); }); function AfficherListe (NomListe) { gUI_Ref++; // on change de liste, alors on change de référence var zUI_Ref = gUI_Ref; RunListe (NomListe, gUI_Ref, 0, gWaveNb); } function RunListe(xNomListe, xUI_Ref, lastElemNo, maxElemNb) { Call_Args = { NomListe : xNomListe, // nom de la liste NoElemRef : lastElemNo, // No du dernier élément affiché maxElems : maxElemNb // nombre d'élements à renvoyer }; if (xUI_Ref == gUI_Ref) { $.ajax({ url : 'assets/php/RespLists.php', type : 'POST', data : Call_Args, cache : false, dataType : 'json', error : function(request, error) { alert("Erreur : responseText: "+request.responseText); }, success : function(data) { if (xUI_Ref == gUI_Ref) { if (lastElemNo == 0) $ListBox.empty(); for(var i = 0; i < data['ListElems'].length; i++) { $el = $('<article>').text(data['ListElems'][i]); $el.appendTo($ListBox).delay(80*i).fadeIn(500); } if (data['ListStatus'] != 'finish') window.setTimeout( RunListe, (80*i), xNomListe, xUI_Ref, data['NoElemRef'], maxElemNb ); // pour casser toute récursivité else $MsgBox.text( 'Liste complétée !' ); } } }); } } // fait le job d'affichage de la liste... }); // --> $(document).ready( Ce message a été modifié par No6 - 20 May 2015, 01:10. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
14 May 2015, 06:42
Message
#17
|
|
Macbidouilleur d'Or ! Groupe : Membres Messages : 2 486 Inscrit : 29 Aug 2002 Membre no 3 340 |
La récursion était déjà "terminale", elle ne garde aucune opération en attente comme dans le cas de factorielle(n) = n * factorielle(n - 1) où la multiplication est en attente, et où plus n est grand, plus la pile se remplit.
Dans le cas de la factorielle, on la rend terminale en passant le résultat à une fonction auxiliaire récursive: fact_aux(n, res) = fact_aux (n - 1, n * res) ici la récursion se fait à pile constante, quel que soit n. et factorielle (n) = fact_aux(n, 1) Et l'étape suivante est de remplacer la récursion de fact_aux par une itération classique Mais la récursion reste souvent le plus court chemin vers une solution. J-P |
|
|
14 May 2015, 09:55
Message
#18
|
|
Oui ? Groupe : Membres Messages : 3 889 Inscrit : 24 Jun 2003 Lieu : BZH Membre no 8 224 |
Oui, mais comme je ne sais pas trop comment les interpréteurs JS optimiseront mon code, et s'ils savent vraiment faire la différence entre une récursion terminale ou non...
sinon, un moyen simple, et dans ce cas la, s'aurait été de mettre un goto... Mais il me semble que l'utilisation des labels n'est pas toujours implémenté.... ??? https://developer.mozilla.org/en-US/docs/We...tatements/label Ce message a été modifié par No6 - 14 May 2015, 10:05. -------------------- "Je sais que vous croyez comprendre ce que vous pensez que j'ai dit, mais je ne suis pas sûr que vous réalisiez que ce que vous avez entendu n'est pas ce que je pense."
(Alan Greenspan) |
|
|
Nous sommes le : 26th April 2024 - 11:31 |