Espero no hacer el ridículo, pero estoy tratando de entender qué está pasando en esas dos líneas de código:
document.body.innerHTML = 'something'; alert('something else');Lo que estoy observando es que la alerta se muestra antes de que se actualice HTML (o tal vez sí, pero la página no se ha actualizado/repintado/lo que sea)
Echa un vistazo a este codepen para ver a qué me refiero.
Tenga en cuenta que incluso poner alert en setTimeout(..., 0) no ayuda. Parece que se necesitan más bucles de eventos para que innerHTML actualice la página.
EDITAR:
Olvidé mencionar que estoy usando Chrome y no revisé otros navegadores. Parece que solo es visible en Chrome. Sin embargo, todavía estoy interesado en por qué sucede eso.
La configuración de innerHTML es síncrona, al igual que la mayoría de los cambios que puede realizar en el DOM. Sin embargo, renderizar la página web es una historia diferente.
(Recuerde, DOM significa "Modelo de objeto de documento". Es solo un "modelo", una representación de datos. Lo que el usuario ve en su pantalla es una imagen de cómo debería verse ese modelo. Por lo tanto, cambiar el modelo no instantáneamente cambiar la imagen - toma algún tiempo para actualizar.)
La ejecución de JavaScript y la representación de la página web en realidad ocurren por separado. Para decirlo de manera simple, primero se ejecuta todo el JavaScript en la página (desde el bucle de eventos; vea este excelente video para obtener más detalles) y luego , el navegador muestra cualquier cambio en la página web para que el usuario lo vea. Esta es la razón por la que el "bloqueo" es tan importante: la ejecución de código computacionalmente intensivo evita que el navegador pase el paso "ejecutar JS" y entre en el paso "renderizar la página", lo que hace que la página se congele o tartamudee.
La tubería de Chrome se ve así:
Como puede ver, todo el JavaScript sucede primero. Luego, la página se diseña, diseña, pinta y compone: el "renderizado". No toda esta canalización ejecutará todos los fotogramas. Depende de qué elementos de la página cambiaron, si los hubo, y cómo deben volver a representarse.
Nota: alert() también es síncrono y se ejecuta durante el paso de JavaScript, por lo que aparece el cuadro de diálogo de alerta antes de ver los cambios en la página web.
Ahora puede preguntar: "Espera, ¿qué se ejecuta exactamente en ese paso 'JavaScript' en la canalización? ¿Todo mi código se ejecuta 60 veces por segundo?" La respuesta es "no", y se remonta a cómo funciona el bucle de eventos JS. El código JS solo se ejecuta si está en la pila, desde cosas como detectores de eventos, tiempos de espera, lo que sea. Ver video anterior (de verdad).
https://developers.google.com/web/fundamentals/performance/rendering/
Sí, es síncrono, porque esto funciona (adelante, escríbelo en tu consola):
document.body.innerHTML = 'text'; alert(document.body.innerHTML);// you will see a 'text' alertLa razón por la que ve la alerta antes de ver el cambio de página es que la representación del navegador lleva más tiempo y no es tan rápida como su javascript ejecutándose línea por línea.
La propiedad innerHTML real se actualiza de forma sincrónica, pero el redibujado visual que provoca este cambio ocurre de forma asincrónica.
La representación visual del DOM es asíncrona en Chrome y no sucederá hasta que la pila de funciones de JavaScript actual se haya borrado y el navegador pueda aceptar un nuevo evento. Otros navegadores pueden usar subprocesos separados para manejar el código JavaScript y la representación del navegador, o pueden permitir que algunos eventos tengan prioridad mientras una alerta detiene la ejecución de otro evento.
Puedes ver esto de dos maneras:
Si agrega for(var i=0; i<1000000; i++) { } antes de su alerta, le ha dado al navegador suficiente tiempo para volver a dibujar, pero no lo ha hecho, porque la pila de funciones no se ha borrado ( add aún se está ejecutando).
Si retrasa su alert a través de un setTimeout(function() { alert('random'); }, 1) asíncrono, el proceso de redibujado se adelantará a la función retrasada por setTimeout.
0 , posiblemente porque Chrome da prioridad de cola de eventos a 0 tiempos de espera antes que cualquier otro evento (o al menos antes de los eventos de redibujado).