Foro de elhacker.net

Programación => Desarrollo Web => Mensaje iniciado por: MA40 en 26 Septiembre 2016, 22:45 pm



Título: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: MA40 en 26 Septiembre 2016, 22:45 pm
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

Código
  1. function bloquea() {
  2.  var limite = 10000000000;
  3.  var n = 0;
  4.  for (var i = 0; i < limite; i++) {
  5.    n = i;
  6.  }
  7.  document.write("Terminado!");
  8. }

Y luego, la siguiente página:

Código
  1. <meta charset="utf-8">
  2. <script language="javascript" type="text/javascript" src="bloquea.js"></script>
  3. </head>
  4.  <input type="button" value="Bloquea" onclick="bloquea()">
  5. </form>
  6. </body>
  7. </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:

Código
  1. <meta charset="utf-8">
  2. <script type="text/javascript">
  3.  var xhrObj = getXHRObject();
  4.  xhrObj.onreadystatechange = function() {
  5.    if ( xhrObj.readyState == 4 && 200 == xhrObj.status ) {
  6.      eval(xhrObj.responseText);
  7.    }
  8.  };
  9.  xhrObj.open('GET', 'bloquea.js', true);
  10.  xhrObj.send('');
  11. </head>
  12.  <input type="button" value="Bloquea" onclick="bloquea()">
  13. </form>
  14. </body>
  15. </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:

Código
  1. <meta charset="utf-8">
  2. <script type="text/javascript">
  3.  var xhrObj = getXHRObject();
  4.  xhrObj.onreadystatechange = function() {
  5.    if ( xhrObj.readyState == 4 ) {
  6.  var scriptElement = document.createElement('script');
  7.  document.getElementsByTagName('head')[0].appendChild(scriptElement);
  8.  scriptElement.text = xhrObj.responseText;
  9.    }
  10.  };
  11.  xhrObj.open('GET', 'bloquea.js', true);
  12.  xhrObj.send('');
  13. </head>
  14.  <input type="button" value="Bloquea" onclick="bloquea()">
  15. </form>
  16. </body>
  17. </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:

Código
  1. <meta charset="utf-8">
  2. <script type="text/javascript">
  3.  var scriptElement = document.createElement('script');
  4.  scriptElement.src = 'bloquea.js';
  5.  document.getElementsByTagName('head')
  6.  [0].appendChild(scriptElement);
  7. </head>
  8.  <input type="button" value="Bloquea" onclick="bloquea()">
  9. </form>
  10. </body>
  11. </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:

Código
  1. <meta charset="utf-8">
  2. <script defer="" src="bloquea.js"></script>
  3. </head>
  4.  <input type="button" value="Bloquea" onclick="bloquea()">
  5. </form>
  6. </body>
  7. </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.


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: Eleкtro en 26 Septiembre 2016, 23:39 pm
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/1248295
Código
  1. setTimeout(function () {
  2.    ... do the rest of the work...
  3. }, 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


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: MA40 en 27 Septiembre 2016, 12:52 pm
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.


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: AlbertoBSD en 27 Septiembre 2016, 13:55 pm
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



Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: [u]nsigned en 27 Septiembre 2016, 16:26 pm
1) los JS siempre van al final de la pagina, justo antes de cerrar </body>

2) Para evitar el bloqueo se usan promises (promesas).


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: MA40 en 27 Septiembre 2016, 17:04 pm

1) los JS siempre van al final de la pagina, justo antes de cerrar </body>


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.


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: [u]nsigned en 27 Septiembre 2016, 17:10 pm
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.


Título: Re: ¿Evitar que se bloqueen los navegadores al cargar un javascript?
Publicado por: MA40 en 27 Septiembre 2016, 17:33 pm

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.


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.