PDA

Ver la versión completa : Problema con Ajax



smaug_
09-07-2008, 10:00
Buenos dias, a ver si alguien por aqui alguna vez se ha tenido que enfrentar a ajax y le ha surgido un problema parecido al mio.
Estoy haciendo una aplicacion web y decidií hacerla con ajax, una tecnologia que no he usado nunca hasta hace dos semanas. Hasta el momento he estado haciendo las pruebas usando Opera, y ahora que la tengo montada casi entera, me doy cuenta que no funciona con otro navegador (he probado iexplorer, firefox y safari). Y no tengo ni idea de porque es, os pongo las partes del codigo mas interesantes:

Estas son las funciones principales, la que carga elobjeto XMHTTP y la funcion general de peticion de contenidos.


function start_xhr(){
if(window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else if ( window.ActiveXObject){
return new ActiveXObject("Microsoft.XMLHTTP");
}
}

function loadContent(url,method,funcion,param){

peticion = start_xhr();
if(peticion){
peticion.overrideMimeType('text/xml');

peticion.onreadystatechange=funcion;
peticion.open(method,url,false);

peticion.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
peticion.send(param);

}
}


Este seria el par de funciones, la primera es la encargada de montar la peticion y la siguiente de mostrar los resultados:



function llenaConsejeria(){
tabla="Consejeria";
campo="consejeria";
query="Buscar=Buscar&tabla="+tabla+"&campo="+campo;
lista=document.getElementById('area');
area=document.getElementById('area').options[lista.selectedIndex].value;
alert(area);
if(area!=null && area!='' && area!='NA') query+="&area="+area;
loadContent("http://localhost/apli/consulta.php","POST",muestraConsejeria,query);
}

function muestraConsejeria(){
var cad=peticion.responseText;
capa='consejeria';
rellenaCombo(cad,capa);
}

En la segunda funcion, se llama para rellenar a la funcion rellenaCombo, pero funciona perfectamente. Tras investigar, parece que el fallo esta en que la funcion de muestra nunca se llega a ejecutar. Vamos la funcion que le pasamos a peticion.onreadystatechange nunca llega a ejecutarse.
A que podria ser debido? En todos los manuales que he visto, esa parte se hace asi, hay distinción entre navegadores para esa parte??
Gracias y un saludo.

Ktorce
09-07-2008, 12:41
Wenas.

Ahora mismo no te se decir que es lo que te falla exactamente. Podrian ser varias cosas:

* La llamada peticion.open la haces despues de peticion.onreadystatechange.
* Instancias peticion cada vez que llamas a loadContent, pero luego llamas a esa variable desde otra funcion (variable global ?)
* No se que es "funcion", que se llama en el onreadystatechange;
* No preguntas por el estado del cambio de estado;

Te pongo como lo tengo yo en una aplicacion que tengo por aquí tanto para metodos POST como GET, a ver si te vale de ejemplo ( me funciona tanto en ie como en firefox)



var req = createXMLHttpRequest();

function createXMLHttpRequest() {
var ua;
if(window.XMLHttpRequest) {
try {
ua = new XMLHttpRequest();
} catch(e) {
ua = false;
}
} else if(window.ActiveXObject) {
try {
ua = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
ua = false;
}
}
return ua;
}

function cargaPage(url,ndiv) {
document.getElementById(ndiv).innerHTML = "<img src='./img/progress.gif'>";
req.open("GET",url);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Connection", "close");
req.onreadystatechange = function() {
if (req.readyState == 4) {
resp = req.responseText;
document.getElementById(ndiv).innerHTML = resp;
}
}
req.send("");
}
function accionPOST(url,ndiv,form) {
document.getElementById(ndiv).innerHTML = "<img src='./img/progress.gif'>"
var param="";
if(form=="frmPassChange") {
accion = "doPassChange";
}else if(form=="frmResetAuras"){
accion = "doResetAuras";
}
param = "&accion="+accion;
for(i=0;i < document.getElementById(form).elements.length;i++) {
param = param+"&"+document.getElementById(form).elements[i].name+"="+document.getElementById(form).elements[i].value;
}
param = encodeURI(Right(param,param.length - 1));
req.open("POST",url);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.setRequestHeader("Content-length", param.length);
req.setRequestHeader("Connection", "close");
req.onreadystatechange = function() {
if (req.readyState == 4) {
resp = req.responseText;
document.getElementById(ndiv).innerHTML = req.responseText;
}
}
req.send(param);
}


Lo de :


document.getElementById(ndiv).innerHTML = "<img src='./img/progress.gif'>"

Lo unico que hace es mostrar una imagen desde que se inicia la accion, hasta que el servidor devuelve la respuesta

Espero te sirva.

Un saludo

smaug_
18-07-2008, 02:19
Gracias por contestar Ktorce, y siento la tardanza, estaba de vacaciones, y sin internet (que mono tenia! )
Conseguí solucionar el problema, todo se debia a que no terminaba de entender la filosofia de Ajax.

Comento la solucion por si alguien vuelve a tener problemas.

Las peticiones se pueden hacer de dos formas, sincronas o asincronas.
En caso de ser asincronas, hace todas las peticiones a la vez, y las suele ir tratando segun venga. Por ello, en peticion.onreadystatechange, le asignamos la funcion encargada de tratar el resultado de la peticion. Y dentro de esta peticion, tenemos que controlar que el contenido este listo.
Un ejemplo de peticion asincrona sería:


function loadContent(url,method,funcion,param){

peticion = start_xhr();
if(peticion){
peticion.overrideMimeType('text/xml');

peticion.onreadystatechange=funcion;
peticion.open(method,url,true);

peticion.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
peticion.send(param);

}
}
function unaFuncion(){
if (req.readyState == 4) {
resp = req.responseText;
document.getElementById(ndiv).innerHTML = resp;
}
}

loadContent("http://url.es","GET","unaFuncion",null);


En cambio, las llamadas sincronas se resuelven una por una. Hasta que una no esta terminada, no sigue con la otra, de esta forma, no nos hace falta comprobar los estados y la funcion que pasamos a peticion.onreadystatechange nunca se ejecuta, sino que tenemos que ejecutarla a mano. A continuacion, un ejemplo de una llamada sincrona.


function loadContent(url,method,funcion,param){

peticion = start_xhr();
if(peticion){
peticion.overrideMimeType('text/xml');
peticion.open(method,url,false);
peticion.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
peticion.send(param);
funcion();

}
}
function unaFuncion(){
resp = req.responseText;
document.getElementById(ndiv).innerHTML = resp;
}

loadContent("http://url.es","GET","unaFuncion",null);

He puesto en negrita los cambios fundamentales. Para elegir entre sincrona y asincrona, tendremos que pasar como tercer parametro a la funcion open false o true respectivamente.
Y para la llamada a la funcion, dependiendo del modo se hara asignando el nombre de la funcion al atributo onreadystatechange o llamandola implicitamente dentro de la funcion.

KaoS
04-09-2008, 11:30
Muy buenas smaug_, ya que lo has solucionado te quería sugerir que para los próximos proyectos, ya que has entendido como funciona y has implementado AJAX desde 0 una vez utilices alguna librería (YUI, Dojo, Ext, Prototype, Jquery, Motools, ...) que suelen estar testeadas en todos los navegadores y funcionan perfectamente, te ahorrará tiempo y quebraderos de cabeza. Además muchísimas son de código abierto por lo que no tendrás ningún problema y además de Ajax tendrás implementadas 1000 funciones más que te serán muy útiles.

Saludos!

evoarte
05-12-2008, 15:47
ktorce, esta parte no la entiendo:

var param="";
if(form=="frmPassChange") {
accion = "doPassChange";
}else if(form=="frmResetAuras"){
accion = "doResetAuras";
}
param = "&accion="+accion;

y, tampoco por que se establece:
req.setRequestHeader("Content-length", param.length);
req.setRequestHeader("Connection", "close");

he llegado a este post buscando una solución al siguiente problema, cuando envío un formulario mediante post cuando recibo el formulario se inserta un nuevo campo:
undefined='undefined,undefined'

que no tengo idea de que se trata,

gracias, un saludo, jc

Ktorce
09-12-2008, 12:16
mmm, pues sin ver el codigo, no te se decir por que se mete ese parámetro.

Lo de los if, no le hagas mucho caso, hice un copy-paste de un codigo concreto que tengo, y hay partes que sobran sin el contexto general.

Desde hace tiempo uso la librería prototype ( http://www.prototypejs.org/ ) y la verdad es que me ahorra mucho tiempo, y tal y como dice Kaos, ya esta testeada en los navegadores más populares (IE, Firefox, Safari..)

Un saludo