[AJAX] Casse-tête asynchrone

Résolu
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   -  
rico568@hotmail.com Messages postés 1 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,
Voila , je voudrait réussir a charger des élément depuis ma base de donnée , en passant par du javascript et des HttpRequest.

Pour l'instant , j'ai réussi a faire cela , mais tout les élément sont chargé en même temps , je m'explique :

J'ai trois fonction :
-Une fonction 'globale' qui orchestre la boucle principale en fonction des paramètres entrés
-Une fonction qui se charge de lancer le chargement en asynchrone pour un élément donné
-Une fonction qui traite les donnée d'un élément quand le chargement de cet élément est finit

Mon problème :
J'utilise dans la fonction 'principale' une boucle for , mais apparement , celle ci n'attend pas que les donnée de la case précédente soit traité pour continuer , j'ai donc 81 HttpRequest qui se lance en même temps ,et ca fait planter 1 fois sur 2 mon navigateur web (on le comprend)

Donc : Comment je pourrais faire pour que la boucle principale attende que les données soit arrivées et traité avant de continuer , sachant que je ne veut pas bloquer le navigateur du visiteur ?

Merci d'avance

PS : Si vous avez besoin du code dites le moi ...

5 réponses

Alain_42 Messages postés 5361 Date d'inscription   Statut Membre Dernière intervention   894
 
C'est sur qu'avec le code on comprendrait mieux.

Mais si tu veux synchroniser, utilises une variable "compteur"
premier envoi HttRequest $cpt=1 tu envoie ce nombre au script "distant" qui l'incrémente de 1 et te le retourne avec le résultat
et tu utilises ce nouveau chiffre pour envoyer la requette suivante

etc...
1
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17
 
Merci de ta réponse , pour le compteur , c'est bon , j'envoie déjà les coordonées concernées 'In URL' , et en fonction le serveur renvoi la bonne réponse ..
Le problème c'est pour faire 'patienter' Javascript , qui m'a l'air d'être un langage qui ne sait pas attendre sans tout bloquer ;) !


Voila donc mon code , j'ai essayé de commenter mais je sait pas trop si le résultat est probant :


La fonction générale que j'appelle , avec pour argument , les coordonnée x,y de n'importe quelle case de mon 'monde'.
//Fonction de gestion globale
function loadmap(x,y)
{
//Initialisation des variables qui indiquent la div dans laquel on doit afficher
	var affx=0;
	var affy=0;

//On teste que les parametre entré soit correcte , sinon on les modifi
	if(x<1){x=1;}
	if(y<1){y=1;}
	if(x>171){x=171;}
	if(y>171){y=171;}
	
	if(((x-1)/9)!=Math.floor((x-1)/9)){x=Math.floor(x/9)*9+1;}
	if(((y-1)/9)!=Math.floor((y-1)/9)){y=Math.floor(y/9)*9+1;}

//On met a jour les fleches qui permettent de se déplacer d'un territoire a l'autre
	document.getElementById('gauche').onclick=function() { loadmap(x-9,y);}
	document.getElementById('droite').onclick=function() { loadmap(x+9,y);}
	document.getElementById('bas').onclick=function() { loadmap(x,y+9);}
	document.getElementById('haut').onclick=function() { loadmap(x,y-9);}

//On boucle du coin x,y indiqué jusque , X+8 et y+8 (soit 9x9 cases) 
	for(posx=x;posx<x+9;posx++)
	{
		affx=affx+1;
		affy=0;
		for(posy=y;posy<y+9;posy++)
		{
			affy=affy+1;
		//On vide la case
			document.getElementById(affx*10+affy).onmouseover=function() { overlib("<center>"+posx+" x "+posy+"</center>",WIDTH, 60);}
			document.getElementById(affx*100+affy).src="images/map_0.png";
		//On lance la fonction qui va faire la requette pour la remplir
			map(posx,posy,affx,affy);
		}
	}
}

Dans cette fonction c'est la boucle 'for' qui me préoccupe , car apparemment , c'est elle qui refuse d'attendre la fin de sont contenu pour continuer..


La fonction qui lance les requêtes :
//Rempli les différentes cases
function map(posx,posy,affx,affy)
{
//On crée une variable pour receuillir le résultat
	var xhr=null;
    
//On crée les HttpRequest
	if (window.XMLHttpRequest) { 
        xhr = new XMLHttpRequest();
    }
    else if (window.ActiveXObject) 
    {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
	
//On défini ce que le navigateur doit faire la fin de la requete
    xhr.onreadystatechange = function() { maj_case(xhr,posx,posy,affx,affy); };
	
//On lance la requette
    xhr.open("GET", "rep_map.php?x="+posx+"&y="+posy, true);
	
//Heu on fait un truc que je sait pas a quoi ca sert ;)
    xhr.send(null);
}

Celle ci n'a rien de particulier , elle lance une requête en définissant ce que JS doit faire a la fin.


Et pour finir de bien charger le message , la fonction de gestion de la réponse du serveur :D !
//Fonction qui permet de gerer la réponse du serveur
function maj_case(xhr,posx,posy,affx,affy)
{
	
//On définit les variables
	var docXML= xhr.responseXML;
	var items = docXML.getElementsByTagName("donnee");

//Si une réponse (pas sur que ce soit ca ...)
	if(items)
	{
	//On définit une variable pour le contenu de la bulle d'option
		var option ="";
	//Si la case est non vide
		if(items.item(1).firstChild.data>1)
		{
		//On teste le contenu de la case et on met l'image en conséquence
			if(items.item(1).firstChild.data==4)
			{
				document.getElementById(affx*100+affy).src="images/map_"+items.item(1).firstChild.data+"_"+items.item(2).firstChild.data+".png";
			}
			else
			{
				document.getElementById(affx*100+affy).src="images/map_"+items.item(1).firstChild.data+".png";
			}
			
		//On teste a présent les options disponibles :
			if(items.item(5).firstChild.data==1)
			{
				option="<center><br><a href=troupe.php?act=0&origin=map&posx="+posx+"&posy="+posy+">Conqu&eacute;rir depuis le chateau</a></center>";
			}
			
			if(items.item(5).firstChild.data==2)
			{
				option="<center>Vous ne pouvez pas conquérir<br>des terrains abandonnée sur une autre zone que la votre.</center>";
			}
			
			if(items.item(5).firstChild.data==3)
			{
				option="<center><br><a href=troupe.php?act=0&origin=map&posx="+posx+"&posy="+posy+">Attaquer depuis le chateau</a><br>Espionner depuis le chateau</center>";
			}
			
			if(items.item(5).firstChild.data==4)
			{
				option="<center><br><a href=index.php?func=gere&type=1>G&eacute;rer le chateau</a></center>";
			}
			
			if(items.item(5).firstChild.data==5)
			{
				option="<center><br><a href=troupe.php?act=0&origin=choix&posx="+posx+"&posy="+posy+">G&eacute;rer les troupes</a><br><a href=troupe.php?act=0&origin=map&posx="+posx+"&posy="+posy+">D&eacute;placer ici depuis le chateau</a><br><a href=index.php?func=gere&type=1&act=5&posx="+posx+"&posy="+posy+">Am&eacute;liorer&nbsp;le&nbsp;niveau&nbsp;("+items.item(6).firstChild.data+")</a></center>";
			}
		//On met a jour les 'Overlib' des div concernés
			document.getElementById(affx*10+affy).onmouseover=function() { overlib(posx+"&nbsp;x&nbsp;"+posy+"&nbsp;("+items.item(3).firstChild.data+")<br>"+items.item(4).firstChild.data,WIDTH, 60);}
			document.getElementById(affx*10+affy).onclick=function() {  overlib(option,STICKY,CAPTION,posx+"&nbsp;x&nbsp;"+posy+"<br>"+items.item(4).firstChild.data,CENTER,WIDTH, 200,HEIGHT,50,NOCLOSE);}
		}
	}
}


Pour la partie Php , le serveur renvoi un XML avec juste :
<map>
</map>

si la case est vide sinon , quelque chose comme :

<map>
<donnee>Hello</donnee>
</map>

Et voilà , si ça peut vous aider à résoudre mon problème ... Si vous voyez des amélioration à faire dans mon code (et je suis sur que il y en a un paquet ...) n'hésitez pas !
0
Alain_42 Messages postés 5361 Date d'inscription   Statut Membre Dernière intervention   894 > gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention  
 
Je n'ai pas tout décortiqué ton code, mais il faut tester que l'on a bien tout reçu avant de traiter la réponse:

dans la fonction qui traite la réponse rajoutes ces tests:

if (http_request.readyState == 4) {
		if (http_request.status == 200) {
                    //la suite 

               {
{



Sinon moi j'avais fait un truc comme ça:
C'est dans la fonction qui traite la réponse que l'on rappelle à nouveau la fct httpRequest tant que la limite du compteur n'est pas atteinte.
0
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17 > Alain_42 Messages postés 5361 Date d'inscription   Statut Membre Dernière intervention  
 
Merci beaucoup ! Déjà le navigateur ne plante plus !! (même si il ralentit si je lance plein de déplacement d'un coup).

Pour le lancement de la fonction de HttpRequest depuis la fonction de traitement , j'ai déjà essayé mais je n'ai jamais réussi .

Sinon , le seul problème qu'il reste c'est que quand l'utilisateur clique plusieurs fois de suite sur les flèches (sans attendre la fin du chargement) , le script lance plusieurs fois de suite la fonction de chargement , et donc çà rame et je me retrouve avec une carte ou tout les bâtiment des différents territoire dessus.

Ma question :
Comment arrêter l'exécution des fonction quand on clique sur une flèche ??

J'ai modifié le script , maintenant , x et y sont des variables globales , déclaré comme ceci :
<SCRIPT language=JavaScript>x=60;y=60;window.onload=loadmap();</SCRIPT>


La fonction loadmap fait donc maintenant ceci :
//Fonction de gestion globale
function loadmap()
{

//Initialisation des variables qui indiquent la div dans laquel on doit afficher
	var affx=0;
	var affy=0;

//On teste que les parametre entré soit correcte , sinon on les modifi
	if(x<1){x=1;}
	if(y<1){y=1;}
	if(x>171){x=171;}
	if(y>171){y=171;}
	
	if(((x-1)/9)!=Math.floor((x-1)/9)){x=Math.floor(x/9)*9+1;}
	if(((y-1)/9)!=Math.floor((y-1)/9)){y=Math.floor(y/9)*9+1;}

//On met a jour les fleches qui permettent de se déplacer d'un territoire a l'autre
	document.getElementById('gauche').onclick=function() { x=x-9; y=y; loadmap();}
	document.getElementById('droite').onclick=function() { x=x+9; y=y; loadmap();}
	document.getElementById('bas').onclick=function() { x=x; y=y+9; loadmap();}
	document.getElementById('haut').onclick=function() { x=x; y=y-9; loadmap();}

//On boucle du coin x,y indiqué jusque , X+8 et y+8 (soit 9x9 cases) 
	var sauvex=x;
	var sauvey=y;
	for(posx=x;posx<x+9;posx++)
	{
		affx=affx+1;
		affy=0;
		for(posy=y;posy<y+9;posy++)
		{
			affy=affy+1;
		//On vide la case
			document.getElementById(affx*10+affy).onmouseover=function() { overlib("<center>"+posx+"&nbsp;x&nbsp;"+posy+"</center>",WIDTH, 60);}
			document.getElementById(affx*100+affy).src="images/map_0.png";
		//On lance la fonction qui va faire la requette pour la remplir
			map(posx,posy,affx,affy);
		//TENTATIVE DE DETECTION QUI NE MARCHE PAS
			if(x!=sauvex||y!=sauvey) alert('HOOO');
		}
	}
}



Voila , je ne sait pas pourquoi ma tentative de détection échoue :S ...

Merci d'avance
0
Alain_42 Messages postés 5361 Date d'inscription   Statut Membre Dernière intervention   894 > gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention  
 
As tu réussi à résoudre ton pb de cicks multiples ?
0
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17 > Alain_42 Messages postés 5361 Date d'inscription   Statut Membre Dernière intervention  
 
Non hélas , c'est pour cela que j'essaye de détecter le territoire (x,y) que l'utilisateur demande a charger , histoire que si elle change au cour du processus , la boucle s'arrete pour laisser la place au nouveau chargement ...

0
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17
 
Bon voilà j'ai fini , c'est pas mal , et j'utilise pas mal de ton code source ;) !
Merci encore pour ton aide !!!
0
rico
 
oui moi je veux bien ton code, peut-être il pourrait m'aider, j'ai un problème en firefox avec les requetes http, on dirai qu'il n'accepte qu'une seule instance à la fois.
j'ai plusieurs listes déroulantes avec des sous-catégories, si j'appelle une deuxième fois ma fonction makeRequest(), je n'obtiens rien avec firefox.
merci
Rico
0
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17
 
Hum... Mon code a beaucoup évolué depuis, il ne ressemble plus trop a ça , même si je fait toujours des requêtes HTTP.
Voila la partie de code javascript qui se charge des requêtes a mes pages php, elle marche très bien sur firefox et IE, et je pouvais la lancer plusieurs fois d'affiler sans problème (même si je ne la lance plus qu'une fois maintenant, la page php renvoyant toutes les informations d'un coup.) :
//Rempli les différentes cases
function map(debx,deby,finx,finy,affx,affy)
{
//On crée une variable pour receuillir le résultat
	var xhr=null;
	
//On crée les HttpRequest
	if (window.XMLHttpRequest) { 
		xhr = new XMLHttpRequest();
	}
	else if (window.ActiveXObject) 
	{
		xhr = new ActiveXObject("Microsoft.XMLHTTP");
	}
	
//On défini ce que le navigateur doit faire la fin de la requete (lance maj_case avec les parametres donné quand la requete est terminée)
	xhr.onreadystatechange = function() { maj_case(xhr,debx,deby,finx,finy,affx,affy,affy); };
	
//On configure la requete
	xhr.open("GET", "rep_map.php?debx="+debx+"&deby="+deby+"&finx="+finx+"&finy="+finy, true);
	
//Et on la lance
	xhr.send(null);
}

Powered by : The Wall Et Gain Brothers
0
X-Fan Messages postés 805 Date d'inscription   Statut Membre Dernière intervention   24
 
Je ne sais pas si ça a un rapport avec toi mais moi j'avais aussi ce problème que je voulais qu'ajax attende la fin de la requête avant de poursuivre. Ma solution a été de changer:

xmlHttp.open("GET",URL,true);

pour

xmlHttp.open("GET",URL,false);

Le false signifiant que je veux que la requête soit synchrone et le true voulant dire le contraire. Vlà je sais pas si c'était ça ton problème aussi mais je crois que ça y ressemblait peut-être. Vive les noobs du Ajax ^_^
0
gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention   17
 
Je sais pas , j'ai réussi avec tout faire sans changer ce paramètre moi ^^'...

Je crois que cette ligne :
xhr.onreadystatechange = function() { maj_case(xhr,debx,deby,finx,finy,affx,affy,affy); };

Signifie qu'il ne lance la requête que quand xhr change d'état, il suffit de mettre un test dans la fonction ciblée pour vérifié que la requête est bien finie...
Après c'est vrai que je débute en Javascript et AJAX, je le fait plus au feeling donc ^^' ...
0
X-Fan Messages postés 805 Date d'inscription   Statut Membre Dernière intervention   24 > gnomesgames Messages postés 84 Date d'inscription   Statut Membre Dernière intervention  
 
Ok et bien il doit y avoir plusieurs façon de faire mais moi en cherchant j'ai trouvé que ce paramètre touchait justement le synchrone/asynchrone de la requête et je me suis dis que c'était plus facile que changer un tas d'autres trucs. Donc j'ai commencé par là.

Bref, de toute façon, j'ai encore des trucs à apprendre alors je n'irais pas dire que j'ai plus raison que toi. Il risque qu'un jour je doive faire comme toi, qui sait. ^^
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
rico568@hotmail.com Messages postés 1 Date d'inscription   Statut Membre Dernière intervention  
 
En effet l'http request ne voulait pas fonctionner en firefox.
Mon problème se situait ailleurs en fait, firefox ne fonctionnait pas bien en httpRequest car mon formulaire était imbriqué dans une table entre la balise <table> et <tr> (afin d'éviter les espaces qui se crée à cause d'une balise form)
Et bien cela empêche apparement à firefox de reconnaitre les éléments par id.

Tout va bien maintenant.

merci

Rico
0