Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

lucasduarte

[Resolvido] Problema com Requisições Simultâneas

Recommended Posts

Oi pessoal!

 

Meu problema com Ajax é clássico: várias requisições sendo executadas ao mesmo tempo. Já li bastante coisa à respeito disso, mas não consegui ainda resolver especificamente meu problema. Por isso, se puderem me ajudar, eu agradeço.. rs. Provavelmente vocês vão ter mais facilidade..

 

A questão está nas seguintes funções:

 

function busca(id, valor){
var niveis = new Array('geo_macro','geo_uf','geo_micro','geo_mun','fazenda','lote','talhao');
var targets = new Array();
var copia_target=0;

// Percorre os níveis para preencher a array targets
for(var i=0; i<niveis.length; i++){
	if(copia_target==1) targets.push(niveis[i]);
	if(niveis[i]==id) copia_target = 1;		
}

doBusca(id, valor, targets);
}

 

Essa função busca é só para receber o valor do select que chamou a função, sua id e os targets (alvos), que são os selects que vão ser preenchidos com o resultado das requisições baseadas nesses valores passados. Para cada select que vou preencher, é uma requisição. O problema é que o número de selects é dinâmico. Consequente, o número de requisições também pode variar. Por isso, vem a próxima função:

 

function doBusca(origem, valor, targets) // Ela recebe o select de origem, seu valor e uma array com os selects que vão ter que ser preenchidos baseados no valor do de origem.
{
xmlHttp = new Array(); // Criei uma array de requisições xml. Baseado no número de targets que vou ter que preencher, crio a quantidade necessária de requisições.
for(var i=0; i<targets.length; i++){
		xmlHttp[i] = new XMLHttpRequest();
		xmlHttp[i].open("GET", "scripts/consultas_selects.php?origem="+origem+"&valor="+valor+"&target="+targets[i]);  // Vou percorrendo a array com os alvos e passando para o página php de consulta um alvo de cada vez.
		xmlHttp[i].onreadystatechange = function (){
			if (xmlHttp[i].readyState==4){
				var result = eval('(' + xmlHttp[i].responseText + ')');
				var el = document.getElementById(targets[i]);

				for(var i=0; i<result.dados.length;i++){
					el.options[el.options.length] = new Option(result.dados[i].nome,result.dados[i].codigo);
				}
			}
		}
		xmlHttp[i].send(null);
	}
}
}

 

O problema está justamente na função onreadystatechange:

 

		xmlHttp[i].onreadystatechange = function (){
			if (xmlHttp[i].readyState==4){
				var result = eval('(' + xmlHttp[i].responseText + ')');
				var el = document.getElementById(targets[i]);

				for(var i=0; i<result.dados.length;i++){
					el.options[el.options.length] = new Option(result.dados[i].nome,result.dados[i].codigo);
				}
			}
		}
		xmlHttp[i].send(null);

 

Seu objetivo é receber o valor da consulta (estou utilizando JSON), criar o objeto retornado utilizando o eval( ) e depois preencher os selects percorrendo toda a array retornada com os resultados da consulta.

O problema, pelo que eu entendi, é que, como é uma execução assíncrona, até ele executar o onreadystatechange todo com o primeiro valor de i, que está dentro do for, o loop já foi feito e a variável i já ganha outro valor.

 

Por isso, vejo pelo FireBug que as três requisições GET são executadas perfeitamente e o resultado delas também está correto. Porém, dá erro em todos os preenchimentos dos selects. O erro é o seguinte:

 

xmlHttp is undefined

 

Na seguinte linha:

 

if (xmlHttp[i].readyState==4){ 

 

O número de vezes que dá esse erro é 9, em vista das repetições que eu utilizo e pela quantidade de targets (3 targets utilizei no teste).

 

Eu precisaria fazer algo para que a segunda repetição "aguardasse" até que a primeira estivesse concluída antes de trocar todos os valores...

 

O que me dizem? Alguma idéia?

 

Agradeço desde já a ajuda!

Compartilhar este post


Link para o post
Compartilhar em outros sites

você precisa enviar o contador como parâmetro:

                        xmlHttp[i].onreadystatechange = function( i ){
                               if (xmlHttp[i].readyState==4){

assim o i no escopo dessa function, será o mesmo do de lá de fora.

 

 

@macielcr7, essa é a forma errada.

Melhor seria fazer assim, se for usar jQuery: http://www.wbruno.com.br/blog/2009/10/06/combos-dependentes-ajax-jquery/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Maciel, obrigado pela informação!

 

Wiliiam, achei excelente sua sugestão. Muito obrigado..

 

Só tem um porém.. Não chega no readyState 4.

 

Separei a função para visualizar melhor. Ficou da seguinte forma:

 

xmlHttp[i].onreadystatechange = muda(i)

 

E a função muda:

 

function muda(i)
{
if (xmlHttp[i].readyState==4){
   	alert(xmlHttp[i].responseText);
}
}

 

E ele não chega a entrar nesse if.

 

Fiz um teste com um alert(xmlHttp.readyState); e o readyState está sempre como 1.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui solucionar o problema. No método open eu coloquei o boolean false para que a execução não fosse assíncrona e a passagem de parâmetros na onReadyStateChange eu fiz da seguinte forma:

 

xmlHttp[i].onreadystatechange = function(){handleHttpResponse(i);}

 

e a função handle:

 

function handleHttpResponse(i)
{
if (xmlHttp[i].readyState==4){
	var result = eval('(' + xmlHttp[i].responseText + ')');
	var el = document.getElementById(targets[i]);

	for(var i=0; i<result.dados.length;i++){
			el.options[el.options.length] = new Option(result.dados[i].nome,result.dados[i].geocodigo);
	}
}
}

 

Lembrando que tive que definir como globais as arrays de requisições e de alvos:

 

var xmlHttp = new Array();
var targets = new Array();	

 

E no início da função busca eu limpo a array para a próxima execução:

 

function busca(id, valor){
targets = new Array();

 

Obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @lucasduarte, queria te explicar o motivo do que você fez..

 

olhe:

xmlHttp[i].onreadystatechange = muda(i)

quando você fez isso, você executou a function muda.

e você não deveria executar ela.

 

você deveria usar uma function bombada,.. uma function anônima.

http://leobalter.net/desenvolvimento/funcoes-bombadas-ou-function/

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.