Forum Clubic

Stopper une requète dès qu'un résultat est retourné

Salut à toutes et à tous :jap:

J’ai un problème non-bloquant (juste chiant :D) avec une application sur laquelle je taff …

Pour faire simple : j’ai un petit moteur de recherche qui va afficher une liste des résultats trouvés en excluant au fur et à mesure les résultats en fonctions des premières lettres de recherches tapé (pour faire encore plus simple : c’est un “suggest”, la même chose que sur google suggest) …

Par exemple, prenons une table d’éléments que l’ont peut rechercher :

  • CLUBIC
  • CLUBAC
  • CLOCLO
  • COCO

Dans mon champ de recherche, je vais saisir une suite de lettre, et à chaque saisie (utilisation de l’évènement javascript : onkeyup), une requête ajax est envoyé au fichier avec les lettres saisies :

  • je tape C > recherche de tous les termes commençant par C
  • je rajoute un L > recherche de tous les termes commençant par CL
  • je rajoute un U > recherche de tous les termes commençant par CLU

Le problème, c’est que le résultat s’affiche dans un seul et même div (de façon à avoir une liste qui se réduit au fur et à mesure), et que la durée d’exécution des recherches est décroissante > la première recherche est plus longue que la seconde (car plus de résultats), qui elle même est plus longue que la troisième, etc …

Et donc, c’est là que le bat blesse : le résultat pour la requête complète s’affiche presque immédiatement, mais il est ensuite remplacé par les résultats des requêtes plus lentes, qui en terminant leur exécution, remplace le contenus du div de résultat (ce qui est en fait extrêmement logique) :

  • je tape C > la recherche commence pour tous les termes commençant par C
  • je rajoute un L > la recherche commence pour tous les termes commençant par CL
  • je rajoute un U > la recherche commence pour tous les termes commençant par CLU
  • le résultat de la recherche CLU s’affiche (ce que je veux)
  • le résultat de la recherche CL, plus lent à générer car ayant plus de résultat, s’affiche (ce que je ne veux pas)
  • le résultat de la recherche C, encore plus lent à générer, s’affiche (ce que je ne veux pas non plus :D)

Donc j’aimerais savoir si quelqu’un à déjà travailler sur un suggest en ajax, et comment il a résolus ce problème ? … Ou si personne n’est déjà travailler là dessus, qu’elles seraient vos idées pour résoudre ce problème ?

A vot’ bon coeur msieu dame :jap: …

PS : j’utilise le framework ajax openrico en vers 1.1.2 avec le prototype.js en version 1.6.0.2 …
Edité le 14/03/2008 à 12:11

Je n’ai pas travaillé dessus, mais ça reste le même problème que l’auto completion de manière générale, ça ou appuyer sur un bouton (où dans ce cas, faut désactiver le bouton, créer une thread qui se chargera de la réactiver).

En tout état de cause: www.w3.org…

Ca te permet d’annuler une requête :slight_smile:

(mais je sais pas si ça s’applique à tous les browsers)

Autre chose: tu peux aussi conserver la liste des objets request, et les flagger comme annulé pour dire “ne pas changer la valeur du div”.
Edité le 14/03/2008 à 12:57

J’avais des sources avec un bouquin qui proposait un exemple de suggest.
Si tu veux, je te les envois et tu vois si tu peux en tirer quelque chose :neutre:

j’avais pensé à la deuxième solution, je vais essayer de mettre ça en place, car vu que j’utilise un framework tout fait, je n’ai pas accès directement aux méthodes de XMLHttpRequest (m’enfin j’ai pas encore trouvé comment :paf: ) …

Ah… mes sources d’exemple ne vont pas te convenir alors, car c’est fait de A à Z pour apprendre le principe/concept
Edité le 14/03/2008 à 13:57

j’ai trouvé pas mal d’exemple tout fait, mais aucun n’abordes ce problème particulier, et je soupçonne qu’il soit sujet au même “soucis” : la plupart des exemples sont fait avec des petites tables et sont donc très rapide et très réactif, même sur les requêtes génériques …
là j’ai presque 100.000 lignes et ça grossit toutes les semaines … la table est bien indexée, puisque les requêtes précises sont très rapides, mais les requêtes “génériques” qui doivent retourner un bon millier de lignes sont plus lentes dans le traitement et la génération du code HTML à retourner (ce qui, encore une fois, me parait extrêmement logique) …

je ne peux pas utiliser de système de cache, car il faut que les résultats soient à jour …

pour l’instant, la solution que j’ai mise en place consiste à n’effectuer la requête AJAX qu’à partir d’un certains nombres de lettres saisies (en l’occurrence : strictement supérieur à 3 lettres) … ça permet d’éliminer les requêtes vraiment trop grosses, mais même avec 4 lettres, on peut avoir plusieurs centaines de résultats qui vont mettre entre 3 et 4 secondes à se générer, là où la requête “finale” est générer en quelques millisecondes, et donc patatra :neutre: …
j’ai proposé la solution d’augmenter le nombre de lettre obligatoire, mais les utilisateurs ne sont pas d’accord car cela limite trop l’utilisation de cette fonction, et après avoir vu avec eux l’usage qu’ils en font, je rejoins leur point de vue :jap: …

une autre solution que j’avais en tête était de déclencher la requête dès que la saisie est finis, en utilisant un timeout … mais là ça dépend de la vitesse à laquelle tape l’utilisateur : avec quelqu’un de rapide, ce sera parfait … avec quelqu’un d’un peu moins rapide, on retomberas sur le même problème … à moins de mettre un timeout élevé (> 1s), mais là pour le coup ça pourrait agacer les utilisateurs …

donc bon, je vais aller fouiller dans le framework openrico s’il y’a un tableau des requêtes (j’ai vu qu’il y’avait un tableau des URL des scripts, donc il doit bien y 'avoir un truc avec les envois de requêtes) … sinon, je verrais pour en faire un maison :oui:

je vous tiens au jus, et si vous avez d’autres idées, je suis preneur :jap:
Edité le 14/03/2008 à 14:26

Kisscool: tu peux en fait faire un système de cache. Mais JS.

Si tu tapes abc, ça te retourne abcdaire, abcdefg, etc…

C’est déjà quelque chose que tu connais par ta requête précédente. Donc tu peux utiliser ces résultats là plutôt qu’une requête.

Sinon, tu as toujours moyen d’accéder à ton objet HTTP : Javascript n’a pas de visibilité :slight_smile:

Peux-tu indiquer le langage utilisé dans le titre :o !
Je propose, je n’ai fait aucun test ni rien mais personnellement j’essaie toujours de n’utiliser que le minimum de requêtes possibles, je crois que ça colle à ce que dit Sans-Nom, mais ne vaut mieux-il pas lancer une requête sur la première lettre saisie, et après s’occuper du traitement de l’affichage dynamiquement, sachant que toutes les prochaines lettres saisies seront déjà dans les résultats précédents de ta requête?

Je saisie “C”
=> Requête type "LIKE ‘C%’ "
=> Je retournes tous les résultats dans le div
Je rajoute “L” (donc est saisie “CL”)
=> Je trie dans la liste dynamiquement tous les mots différents de CL*

Enfin peut-être j’ai mal compris le problème ou c’est ce que tu fais déjà, dans ce cas là je m’excuserais de l’inutilité de mon message :confused:

Les tags n’ont pas été implémentés pour faire jolis :o

Et pourquoi pas une notion de “temps de démarrage de la requete” ?

Par exemple quand tu lance ta requete ajax tu mémorise la date.

Dans ta méthode d’affichage des suggestions, tu vérifie que la réponse correspond au temps de la requete la plus récente, sinon tu n’affiche rien.

Et tu ne peux pas, tout betement, ajouter le nombre de lettres dans le résultat de ta requête ? (qui aurait la forme, pour “CLU”, de quelque chose comme “3|CLUB|CLUBIC|CLUCLU|CLUEDO|…”)

  • je tape C > la recherche commence pour tous les termes commençant par C
  • je rajoute un L > la recherche commence pour tous les termes commençant par CL
  • je rajoute un U > la recherche commence pour tous les termes commençant par CLU
  • le résultat de la recherche CLU est reçu, en précisant qu’il s’agit d’une recherche de trois lettres. La boite contient trois lettres donc le résultat s’affiche
  • le résultat de la recherche CL, plus lent à générer car ayant plus de résultat, est reçu, précisant qu’il s’agit d’une recherche de deux lettres. La boite contient trois lettres, donc le résultat ne s’affiche pas
  • le résultat de la recherche C, encore plus lent à générer, est reçu, précisant qu’il s’agit d’une recherche d’une seule lettre. La boite contient trois lettres, donc le résultat ne s’affiche pas.
    Edité le 15/03/2008 à 12:51

Je taquinais juste Raynor :peur:

Bon je crois qu’en faite j’ai rien compris au problème, moi j’aurais juste appliquer ma méthode certes pas des plus rapides et qui ne nécessite pas d’Ajax, mais fonctionnelle :confused:

Vu qu’on m’invite (sans raison) dans ce topic je vais donner mon avis :

  1. Solution de tri en JavaScript parmi les résultats de la première requête (qu’elle soit dès la première lettre tapée ou pas) [Sans-Nom et Chameau] :
    Simple mais on fait faire le boulot par JavaScript au lieu d’SQL (CPU utilisé = celui du client).
    Il faudrait cependant bien gérer le cas où le visiteur s’est trompée et qu’elle retire des caractères ([Backspace], [Delete], ou autre)

  2. Solution de filtre des requête arrivantes selon le timestamp de la demande [NeqO] :
    Assez simple et complète rien à redire)

  3. Solution de filtre [kookiz33] :
    Peut-être un poil plus complexe selon la fonction qui effectue la recherche et pas super propre (enfin ça dépends, je n’ai aucune idée de ce à quoi ressemble un flux de résultat pour ce genre de fonctionnalité).
    Et là encore il faut gérer le cas où le visiteur modifie ses critères.

merci pour toutes ces idées :jap:

je vais regarder ça en pratique lundi, parce que le week end c’est relâche :smiley:

si vous avez encore d’autres idées qui fusent dans vos cellules grises, n’hésitez pas :jap: …

Toutes mes confuses, j’me suis trompé de pseudo, je voulais bien entendu dire KisSCoOl :confused: !

Y’a pas de soucis, je ne m’appelle pas Sans-Nom [:kramoc]

KisSCoOl > Alors tu as pu tester nos solutions ?

Je réalise que ma méthode est incomplète :

  • L’utilisateur tape “CL”
  • L’utilisateur tape “U”
  • L’utilisateur efface le “U”
  • L’utilisateur tape “A”

Si la requête correspondant à “CLU” termine à ce moment là, comme il y a bien trois caractères, elle sera affichée alors qu’elle ne correspond plus à la recherche. Il faut donc conserver la saisie qui a déclenché la recherche plutôt que le nombre de caractères :wink:
Edité le 17/03/2008 à 09:48

Raynor: bien sûr que ça utilise le CPU utilisateur :slight_smile: mais de l’auto completion, sur un serveur, c’est un peu le truc qui fait morfler le dit serveur.

Autant utiliser un système de cache simple, sachant qu’il a déjà les réponses à ses questions (ie: il a déjà les résultats), et que ça ne sera pas si lent dans son cas.

Je viens de sortir de la réunion bi-mensuel, donc je m’y mets :o :oui:

bon donc alors, dans un soucis de rapidité (car nous venons de recevoir le feu vert pour une mise à jour du système demain midi :o ), on a privilégié la solution d’un timeout à la saisie, de la forme :


        var objTimeout='';
	
	function launchFunc()
	{
		if ( objTimeout != '' )
		{
			clearTimeout(objTimeout);
		}
		
		args = new Array();
		
		for ( var k=1; k < launchFunc.arguments.length; k++ )
		{
			args.push(launchFunc.arguments[k]);
		}
		
		//self.status = launchFunc.arguments[0] + "('" + args.join("','") + "')";
		
		objTimeout = setTimeout(launchFunc.arguments[0] + "('" + args.join("','") + "')", <?php echo AJAX_WAIT_TIME ?>);
	}

et un appel type :


<input type="text" autocomplete="false" name="email" id="email" size="20" maxlength="255" title="Adresse email" value="" onkeyup="launchFunc('searchC', 'div-res-search');" />

ça fonctionne correctement …

ceci dit, nous avons essayer la solution de NeqO ce matin, mais sans succès car nous n’avons pas (ou ne savons pas comment avoir) accès à la function qui écrit dans le div … j’ai l’impression que sur le framework openrico, une fois la requête lancé, on a plus aucun moyen d’y accéder :confused: il y’a bien l’option de mettre du code à exécuter une fois la requête terminé (onComplete), mais cette fonction n’étant appelé qu’une fois le code HTML envoyé dans le div, on ne peut pas vraiment en faire grande chose … devant le manque de temps pour analyser le code du framework, on a lâcher l’affaire :smiley:

vouala vouala :o
Edité le 17/03/2008 à 16:16