2010-04-24 13 views
31

Estoy escribiendo una aplicación web AJAX que usa Comet/Long Polling para mantener la página web actualizada, y noté que en Chrome trata la página como si siempre estuviera cargándose (icon para la pestaña sigue girando).El indicador de carga de Chrome sigue girando durante XMLHttpRequest

Pensé que esto era normal para Google Chrome + Ajax porque incluso Google Wave tenía este comportamiento.

Bueno, hoy noté que Google Wave ya no mantiene el icono de carga girando, ¿alguien sabe cómo lo solucionaron?

Aquí es mi ajax código de llamada

var xmlHttpReq = false; 
// Mozilla/Safari 
if (window.XMLHttpRequest) { 
    xmlHttpReq = new XMLHttpRequest(); 
} 
// IE 
else if (window.ActiveXObject) { 
    xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP"); 
} 
xmlHttpReq.open('GET', myURL, true); 
xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
xmlHttpReq.onreadystatechange = function() { 
    if (xmlHttpReq.readyState == 4) { 
     updatePage(xmlHttpReq.responseText); 
    } 
} 
xmlHttpReq.send(null); 

Respuesta

36

descaradamente robé caso de prueba de Oleg y ajusté un poco para simular larga -votación.

load.html:

<!DOCTYPE html> 
<head> 
    <title>Demonstration of the jQery.load problem</title> 
    <script src="http://code.jquery.com/jquery-latest.js"></script> 
    <script> 
    jQuery(document).ready(function() { 
    $('#main').load("test.php"); 
    }); 
    </script> 
</head> 
<body> 
    <div id='main'></div> 
</body> 
</html> 

test.php:

<?php 
    sleep(5); 
?> 
<b>OK!</b> 

El resultado es interesante: en Firefox y Opera, no se muestra ningún indicador de carga durante XmlHttpRequests. Chrome lo deja girar ... Sospecho que Google Wave ya no usa encuestas largas (pero, por ejemplo, encuestas cada X segundos, para ahorrar recursos), pero no puedo probarlo, ya que no tengo una cuenta .

EDIT: Y lo he descubierto: después de añadir un poco de retraso en la carga test.php, que puede ser tan pequeño como sea posible, el indicador de carga se detiene después de load.html se ha cargado:

jQuery(document).ready(function() { 
    setTimeout(function() { 
    $('#main').load("test.php"); 
    }, 0); 
}); 

alguna manera, como es confirmed in a comment en otra respuesta, cuando el navegador obtiene control de nuevo para finalizar la representación de la página, el indicador deja de girar. Otra ventaja es que la solicitud no se puede cancelar presionando Esc.

+0

¿Pero no sondear cada x segundos aumentaría la carga en el servidor? Supongo que puede irse de otra manera ahora que lo pienso (Long Polling vs Poling cada x segundos). Pero no estoy seguro de que esté convencido de que cambiaron de Long Polling. –

+0

@teehoo: Una vez leí que las largas encuestas son pesadas sobre los recursos, ya que muchas conexiones deben mantenerse abiertas al mismo tiempo, algo por lo que HTTP no está diseñado. Pero no soy un experto en servidores, así que por favor corrígeme si me equivoco. –

+0

Supongo que mantener abiertas las conexiones requiere más memoria, ¿pero las conexiones de apertura y cierre requieren más CPU + ancho de banda constantemente? Gracias por analizar esto, verificaré que funcione cuando llegue a casa. –

2

Lo siento por mi respuesta general, pero si usted quiere tener un programa que son más independiente del navegador que debe usar jQuery u otra su biblioteca favorita en lugar de bajo XMLHttpRequest nivel y la ActiveXObject ("Microsoft.XMLHTTP").

Editado: puedo crear dos archivos HTML muy simples: test.htm y load.htm y colocado allí en el mismo directorio en un sitio web (URL prueba este http://www.ok-soft-gmbh.com/jQuery/load/load.htm). No puedo ver el efecto que describes en tu pregunta. Compare estos archivos con sus ejemplos y resolverá su problema.

load.htm:

<!DOCTYPE html PUBLIC 
      "-//W3C//DTD XHTML 1.0 Strict//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head id="Head"> 
    <title>Demonstration of the jQery.load problem</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <script src="http://code.jquery.com/jquery-latest.js"></script> 
    <script type="text/javascript"> 
    jQuery(document).ready(function() { 
    $('#main').load("test.htm"); 
    }); 
    </script> 
</head> 

<body> 
    <div id='main'></div> 
</body> 
</html> 

test.htm:

<b>OK!</b> 
+0

No sé quién es usted downvoted, Pondré esto de nuevo en cero porque lo encontré de alguna manera útil. Intentaré con JQuery e informaré. –

+0

intente usar una línea de código en lugar de su fragmento de código: $ ('# elementtoupdate'). Load (myURL); También puede agregar algunos efectos fadeIn u otro. – Oleg

+0

Así que implementé JQuery, e hizo que mi código fuera un poco más limpio, pero todavía obtengo el estado de carga constante. –

-3

uso de esta función

function getHTTPObject() { 
var xhr = false; 
if (window.XMLHttpRequest) { 
    xhr = new XMLHttpRequest(); 
} else if (window.ActiveXObject) { 
    try { 
    xhr = new ActiveXObject("Msxml2.XMLHTTP"); 
    } catch(e) { 
    try { 
    xhr = new ActiveXObject("Microsoft.XMLHTTP"); 
    } catch(e) { 
    xhr = false; 
    }; 
    }; 
}; 
return xhr; 
}; 
+3

¿Se puede formatear mejor? –

0

No estoy seguro acerca de jQuery o Ajax, pero tuve un problema similar al insertar fragmentos en Ace Editor con el Administrador de fragmentos.Al insertar el código en el editor justo cuando la página se estaba cargando, parece que la página nunca se cargó: el ícono de la pestaña giraría para siempre. .setTimeout() solo funcionó de manera muy inconsistente. Funcionaría cuando la página se cargue muy rápido, pero no cuando la página cargó más lentamente. Eso podría ser porque no estaba envolviendo nada en $(document).ready() - Solo estaba llamando a mi código al final del cuerpo del documento.

Aquí es una solución sin jQuery me encontré a mi siempre hilatura problema pestaña icono:

var tillPageLoaded = setInterval(function() { 
    if(document.readyState === 'complete') { 

     clearInterval(tillPageLoaded); 
     // load whatever 

    }  
}, 5); 

En mi caso, // load whatever fue:

ace.config.loadModule('ace/ext/language_tools', function() { 
    myEditorInstance.insertSnippet('some string'); 
}); 
Cuestiones relacionadas