Hola.
Cuando se carga una web que tiene algún javascript que requiere mucho tiempo de cálculo, los navegadores se bloquean y después de unos minutos muestran mensajes para continuar o detener el script.
Sin embargo hay algunas webs que evitan esto (no sé cómo lo harán). Pongo el ejemplo de la siguiente página para jugar al ajedrez: http://forwardcoding.com/projects/ajaxchess/chess.html (http://forwardcoding.com/projects/ajaxchess/chess.html) (para probar, hay que poner el "Time per move:" mayor de 10000 ms).
¿Cómo se puede hacer eso?
Para probar, he hecho el siguiente javascript en el archivo bloquea.js
function bloquea() {
var limite = 10000000000;
var n = 0;
for (var i = 0; i < limite; i++) {
n = i;
}
document.write("Terminado!");
}
Y luego, la siguiente página:
<html>
<head>
<meta charset="utf-8">
<script language="javascript" type="text/javascript" src="bloquea.js"></script>
</head>
<body>
<form>
<input type="button" value="Bloquea" onclick="bloquea()">
</form>
</body>
</html>
Se puede probar aquí: http://bitcart.info/laboratorio/bloquea.htm (http://bitcart.info/laboratorio/bloquea.htm)
Como se puede ver se bloquea, aunque si no se interrumpe voluntariamente el script, después de unos 15 segundos termina.
He estado buscando y encontré esta página en la que creo que se explica cómo solucionar el problema: http://www.frikipandi.com/public/post/cargar-javascript-sin-bloqueo-en-el-navegador/ (http://www.frikipandi.com/public/post/cargar-javascript-sin-bloqueo-en-el-navegador/) Pero, utilizando el archivo bloquea.js, no he conseguido hacer funcionar ninguna de las opciones que describe.
El código de la primera es éste:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
var xhrObj = getXHRObject();
xhrObj.onreadystatechange = function() {
if ( xhrObj.readyState == 4 && 200 == xhrObj.status ) {
eval(xhrObj.responseText);
}
};
xhrObj.open('GET', 'bloquea.js', true);
xhrObj.send('');
</script>
</head>
<body>
<form>
<input type="button" value="Bloquea" onclick="bloquea()">
</form>
</body>
</html>
Y se puede probar aquí: http://bitcart.info/laboratorio/nobloquea_1.htm (http://bitcart.info/laboratorio/nobloquea_1.htm)
Bloquearse, no se bloquea, pero nunca termina, por lo que pienso que no entra en el bucle.
La segunda opción es ésta:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
var xhrObj = getXHRObject();
xhrObj.onreadystatechange = function() {
if ( xhrObj.readyState == 4 ) {
var scriptElement = document.createElement('script');
document.getElementsByTagName('head')[0].appendChild(scriptElement);
scriptElement.text = xhrObj.responseText;
}
};
xhrObj.open('GET', 'bloquea.js', true);
xhrObj.send('');
</script>
</head>
<body>
<form>
<input type="button" value="Bloquea" onclick="bloquea()">
</form>
</body>
</html>
Y para probar: http://bitcart.info/laboratorio/nobloquea_2.htm (http://bitcart.info/laboratorio/nobloquea_2.htm)
El resultado es el mismo que el de la anterior.
Tercera opción:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
var scriptElement = document.createElement('script');
scriptElement.src = 'bloquea.js';
document.getElementsByTagName('head')
[0].appendChild(scriptElement);
</script>
</head>
<body>
<form>
<input type="button" value="Bloquea" onclick="bloquea()">
</form>
</body>
</html>
Y para probar: http://bitcart.info/laboratorio/nobloquea_3.htm (http://bitcart.info/laboratorio/nobloquea_3.htm)
Sí se bloquea, y también termina.
Cuarta opción:
<html>
<head>
<meta charset="utf-8">
<script defer="" src="bloquea.js"></script>
</head>
<body>
<form>
<input type="button" value="Bloquea" onclick="bloquea()">
</form>
</body>
</html>
Para probar: http://bitcart.info/laboratorio/nobloquea_4.htm (http://bitcart.info/laboratorio/nobloquea_4.htm)
Lo mismo, se bloquea y termina.
La quinta opción ya no la he probado.
¿Alguien puede ayudarme?
Un saludo.
No se si te servirá de algo, pero lee esta respuesta:
- Why doesn't javascript support multithreading? - StackOverflow (http://stackoverflow.com/a/39961/1248295)
Al parecer podrias utilizar el método
window.setTimeout() en la implementación de tu algoritmo para evitar que se bloquee el hilo del render mientras se procesan las operaciones expensivas que necesites llevar a cabo, o eso es lo que entendí según lo que parece poner en esa respuesta...
Ejemplo:
Cita de: http://stackoverflow.com/a/39922/1248295setTimeout(function () {
... do the rest of the work...
}, 0);
Y si eso no funciona, esto otro seguro que lo hará, puesto que en teoría te permitirá ejecutar tareas de forma asincrónica (por ende, el hilo principal de la web/navegador no se bloqueará):
- http://keithwhor.github.io/multithread.js/
PD: Yo no uso javascript.
Saludos
Hola.
Encontré esta otra dirección, muy interesante y en español, donde se explica cómo podrían programarse multihilos con la librería Concurrent.Thread.js (https://github.com/bringmehome/Concurrent.Thread.js (https://github.com/bringmehome/Concurrent.Thread.js))
La dirección: http://www.purojavascript.com/2012/07/documento-sin-titulo.html (http://www.purojavascript.com/2012/07/documento-sin-titulo.html)
Un saludo.
Otra opcion igual de valida seria enviar los datos al servidor y que este los procese, y tener un script que se ejecute cada x segundos para comprobar si el servidor ya acabo de procesar los datos y en ese caso mostrarlos.
Saludos
1) los JS siempre van al final de la pagina, justo antes de cerrar </body>
2) Para evitar el bloqueo se usan promises (promesas).
[quote author=nsigned link=topic=458291.msg2089829#msg2089829 date=1474986418]
1) los JS siempre van al final de la pagina, justo antes de cerrar </body>
[/quote]
http://librosweb.es/libro/javascript/capitulo_1/como_incluir_javascript_en_documentos_xhtml.html (http://librosweb.es/libro/javascript/capitulo_1/como_incluir_javascript_en_documentos_xhtml.html)
:huh: :huh: :huh: :huh: :huh:
(http://www.bitcart.info/laboratorio/js.jpg)
MOD: Imagen reimensionada a lo usado en el foro.
Eso está mal, lo correcto es ponerlos donde te dije yo. Asi cargan de ultimo, porque los js bloquean la carga,e s decir mientras se cargan no carga nada mas, por esos ponerlo al final del body.
[quote author=nsigned link=topic=458291.msg2089836#msg2089836 date=1474989050]
Eso está mal, lo correcto es ponerlos donde te dije yo. Asi cargan de ultimo, porque los js bloquean la carga,e s decir mientras se cargan no carga nada mas, por esos ponerlo al final del body.
[/quote]
Gracias {u}nsigned, tomamos nota.
En cuanto a lo de evitar el bloqueo en navegadores ¿cómo se podría resolver con promises? ¿Podrías poner el código para mi primer ejemplo (el de bloquea.js)?
Muchas gracias y un saludo.