2009-08-03 26 views
8

Por lo general, administro la mejora progresiva mientras mantengo la experiencia limpia, pero ¿qué tan seguro es? ¿hay potencial para una condición de carrera y esto no funciona?¿Está bien manipular dom antes del estado preparado?

imaginar el escenario simple resumen, que desea mostrar algo diferente si tiene Javascript apoyo .. esto es generalmente lo que voy a terminar haciendo:

<div id="test">original</div> 
<script type="text/javascript"> 
    var t = document.getElementById('test'); 
    t.innerHTML = 'changed'; 
</script> 

Muchos pueden reclamar que debe utilizar un marco y esperar para un evento domready, y hacer cambios allí ... sin embargo, hay un retraso significativo donde el elemento 'prueba' ya habrá sido renderizado antes del final del documento y el CSS está listo y se dispara un prearranque .. causando así un parpadeo notorio de 'original'.

¿Este código es susceptible de fallas de condición de carrera? o ¿puedo garantizar que un elemento sea detectable y modificable si existe antes del script?

Gracias de antemano.

Respuesta

5

Puede, pero hay problemas que lo rodean.

Primero, en IE si intentas manipular un nodo que no ha sido cerrado (por ej. BODY antes de su etiqueta de cierre que debería estar debajo de tu JS) entonces puedes encontrar el error "OPERACIÓN ABORDA" de IE que dará como resultado página en blanco. La manipulación de un nodo incluye nodos anexos, nodos móviles, etc.

En otros navegadores, el comportamiento no está definido, sin embargo, generalmente se comportan como era de esperar. El problema principal es que a medida que su página evoluciona, la página puede cargar/analizar/ejecutar de manera diferente. Esto puede provocar que se ejecute algún script antes de que un navegador defina que los elementos referenciados se hayan creado realmente y estén disponibles para la manipulación de DOM.

Si está intentando mejorar el rendimiento percibido por el usuario (es decir, la ligereza). Te sugiero que evites este camino y veas cómo aligerar tus páginas. Puede usar YSlow de Yahoo/Google Performance Firebug de Google para ayudarlo a comenzar.

Google's Page Speed

Yahoo's YSlow

+0

Hola Raegx, sí, puedo entender completamente el problema de operación abortada con elementos cambiantes que no se han cerrado ... en términos de la ligereza, estas páginas son livianas, la página real es de 15kb ... sin embargo, mi elemento cambiado bien puede estar justo debajo de la etiqueta del cuerpo de apertura, y se renderizará antes de los fuegos dominantes, independientemente de cuán liviana sea mi página. Estoy tratando de evitar una experiencia descuidada eso siempre se experimenta imo con domready y haciendo este tipo de cosas. – meandmycode

+0

Ya en la edad de las tinieblas, cuando no teníamos una forma de navegador cruzado para disparar aDomReady solíamos usar onLoad, que se disparaba después de cargar y renderizar todas las imágenes/css/etc. Ahora tenemos onDomReady que se activa después de que el DOM ha sido analizado y representado, pero potencialmente antes de las imágenes/etc. Este es un avance relativamente nuevo también. Así que esperar a OnDomReady es todo lo que tenemos en este momento y es la mejor solución para la robustez. Si crees que tu manipulación antes de onDomReady vale la pena y no estás agregando/creando/moviendo nodos a nodos no abiertos, probablemente estés bien. –

+0

Genial, vale la pena si funciona ... por lo que estoy escuchando, debería funcionar bien, pero no hay nada que indique oficialmente que un elemento debe estar listo después de su nodo de cierre. – meandmycode

3

Puede manipular el DOM antes de que se haya cargado por completo, pero puede ser riesgoso. Obviamente, no puede garantizar que la parte del DOM que intenta manipular realmente exista todavía, por lo que su código puede fallar intermitentemente.

+0

Gracias rikh, ¿qué quiere decir theres ninguna garantía, por especificación o por la realidad actual de los productos que existen en la actualidad (ff, es decir, ópera, etc.). Creo que el analizador actúa linealmente y agrega elementos a medida que encuentra su nodo de cierre.aunque esto puede no ser una especificación, creo que este es un comportamiento sensato, y estaba buscando más para encontrar autorizar las respuestas que este es el caso. – meandmycode

+1

Para ser sincero, no lo sé, pero no es algo de lo que me gustaría depender. Si realmente está preocupado por la información incorrecta que se muestra, intente mostrar nada inicialmente, y luego complete algo en el doc ready, o simplemente diseñe el problema fuera del sistema, para que no tenga que hacer lo que está pidiendo. –

+0

Desafortunadamente eso no es posible, el último ejemplo que tengo es donde renderizamos números de paginación como hipervínculos, y nuestro javascript se ejecuta y los cambia para que podamos mostrar 'Página x de y' y resaltar el hipervínculo de página que está activo (las páginas son anclajes). Este es un típico escenario de mejora progresiva en el que renderizamos algo que funcionará sin javascript ... y luego lo interceptaremos y lo modificaremos con javascript para usar javascript. El hecho de que pueda manipularlo con javascript lo demuestra. .tiene soporte de Javascript;) – meandmycode

1

Mientras solo modificar nodos que preceden el bloque de script (es decir, etiqueta de cierre del nodo precede etiqueta de apertura de la secuencia de comandos), no debería encontrar ningún problema.

Si desea asegurarse de que la operación tenga éxito, envuelva el código en un bloque try...catch y llámelo nuevamente a través de setTimeout() en caso de falla.

+0

Gracias Christoph, estaba considerando que al fallar no obtendría nada ni una excepción y podría intentarlo ... aunque no me gusta esa lógica de reintento, me preocupa que la ejecución pueda dificultar el rendimiento de carga de la página. Estoy Voy a ver si puedo ejecutar algunas pruebas tratando de simular ancho de banda altamente restringido e incluso bajo poder de procesamiento para ver si puedo encontrar cualquier ventana que exista ... hasta ahora el ancho de banda no parece hacer nada, he estado ejecutando iteraciones de la página cargándose a 100 bytes por segundo (lleva un tiempo) ... y para cuando el área ha cargado, ya ha ... – meandmycode

+0

... ejecuté el script perfectamente bien ... Imagino que restringir el tiempo de procesamiento es mucho más probable paralizar el analizador e iluminar cualquier ventana donde la suposición es incorrecta. – meandmycode

0

En Viajeros.com tengo un indicador de carga trabajando desde hace 8-9 meses y hasta ahora no tengo ningún problema. Se ve así:

<body> 

<script type="text/javascript"> 
    try { 
     document.write('<div id="cargando"><p>Cargando...<\/p><\/div>'); 
     document.getElementById("cargando").style.display = "block"; 
    } catch(E) {}; 
</script> 
+2

Quizás ese no sea todo el código, pero te das cuenta de que 'getElementById' es completamente innecesario, ¿no? Simplemente puede agregar 'style = 'display: block" 'al HTML. – DisgruntledGoat

-1

acceder al DOM lanza prematuramente excepciones en IE 5 y Navigator 4.

Cuestiones relacionadas