He tenido la impresión de que JavaScript siempre fue asíncrono. Sin embargo, he aprendido que hay situaciones en las que no es así (es decir, manipulaciones DOM). ¿Hay alguna buena referencia sobre cuándo será síncrono y cuándo será asíncrono? ¿JQuery afecta esto en absoluto?
javascript
jquery
Brian
fuente
fuente
Respuestas:
JavaScript siempre es síncrono y de subproceso único. Si está ejecutando un bloque de código JavaScript en una página, entonces no se ejecutará ningún otro JavaScript en esa página.
JavaScript solo es asíncrono en el sentido de que puede hacer, por ejemplo, llamadas Ajax. La llamada Ajax dejará de ejecutarse y otros códigos podrán ejecutarse hasta que la llamada regrese (con éxito o no), momento en el que la devolución de llamada se ejecutará de forma sincrónica. Ningún otro código se ejecutará en este momento. No interrumpirá ningún otro código que se esté ejecutando actualmente.
Los temporizadores de JavaScript funcionan con este mismo tipo de devolución de llamada.
Describir JavaScript como asíncrono es quizás engañoso. Es más exacto decir que JavaScript es sincrónico y de un solo subproceso con varios mecanismos de devolución de llamada.
jQuery tiene una opción en llamadas Ajax para hacerlas sincrónicamente (con la
async: false
opción). Los principiantes pueden verse tentados a usar esto incorrectamente porque permite un modelo de programación más tradicional al que uno podría estar más acostumbrado. La razón por la que es problemático es que esta opción bloqueará todo JavaScript en la página hasta que finalice, incluidos todos los controladores de eventos y temporizadores.fuente
JavaScript es de un solo subproceso y tiene un modelo de ejecución síncrono. Un solo subproceso significa que se está ejecutando un comando a la vez. Sincrónico significa uno a la vez, es decir, se está ejecutando una línea de código a la vez en el orden en que aparece el código. Entonces, en JavaScript, una cosa está sucediendo a la vez.
Contexto de ejecución
El motor de JavaScript interactúa con otros motores en el navegador. En la pila de ejecución de JavaScript hay un contexto global en la parte inferior y luego, cuando invocamos funciones, el motor de JavaScript crea nuevos contextos de ejecución para las funciones respectivas. Cuando la función llamada sale, su contexto de ejecución aparece de la pila, y luego aparece el siguiente contexto de ejecución, etc.
Por ejemplo
En el código anterior se creará un contexto de ejecución global y en este contexto
var one
se almacenará y su valor será 1 ... cuando se invoque la invocación xyz (), se creará un nuevo contexto de ejecución y si hubiéramos definido alguna variable en la función xyz, esas variables se almacenarían en el contexto de ejecución de xyz (). En la función xyz invocamos abc () y luego se crea el contexto de ejecución abc () y se coloca en la pila de ejecución ... Ahora, cuando abc () termina, su contexto se extrae de la pila, entonces el contexto xyz () se extrae de apilar y luego aparecerá el contexto global ...Ahora sobre devoluciones de llamada asincrónicas; asíncrono significa más de uno a la vez.
Al igual que la pila de ejecución, está la Cola de eventos . Cuando queremos que se nos notifique sobre algún evento en el motor de JavaScript, podemos escuchar ese evento, y ese evento se coloca en la cola. Por ejemplo, un evento de solicitud Ajax o un evento de solicitud HTTP.
Siempre que la pila de ejecución esté vacía, como se muestra en el ejemplo de código anterior, el motor de JavaScript revisa periódicamente la cola de eventos y ve si hay algún evento sobre el que se deba notificar. Por ejemplo, en la cola hubo dos eventos, una solicitud ajax y una solicitud HTTP. También busca ver si hay una función que deba ejecutarse en ese desencadenador de eventos ... Entonces, el motor de JavaScript recibe una notificación sobre el evento y conoce la función respectiva que se ejecutará en ese evento ... Entonces, el motor de JavaScript invoca el función de controlador, en el caso de ejemplo, por ejemplo, se invocará AjaxHandler () y, como siempre cuando se invoca una función, su contexto de ejecución se coloca en el contexto de ejecución y ahora la ejecución de la función finaliza y la solicitud de evento ajax también se elimina de la cola de eventos ... Cuando AjaxHandler () finaliza, la pila de ejecución está vacía, por lo que el motor vuelve a mirar la cola de eventos y ejecuta la función de controlador de eventos de la solicitud HTTP que fue la siguiente en la cola. Es importante recordar que la cola de eventos se procesa solo cuando la pila de ejecución está vacía.
Por ejemplo, vea el siguiente código que explica la pila de ejecución y el manejo de la cola de eventos mediante el motor Javascript.
Y
Ahora ejecute la página web y haga clic en la página, y vea el resultado en la consola. La salida será
El motor de JavaScript ejecuta el código de forma síncrona como se explica en la parte del contexto de ejecución, el navegador pone las cosas en la cola de eventos de forma asíncrona. Por lo tanto, las funciones que tardan mucho tiempo en completarse pueden interrumpir el manejo de eventos. Las cosas que suceden en un navegador, como los eventos, son manejadas de esta manera por JavaScript, si se supone que un oyente debe ejecutarse, el motor lo ejecutará cuando la pila de ejecución esté vacía. Y los eventos se procesan en el orden en que ocurren, por lo que la parte asincrónica se trata de lo que sucede fuera del motor, es decir, qué debe hacer el motor cuando ocurren esos eventos externos.
Entonces JavaScript es siempre sincrónico.
fuente
JavaScript es de un solo subproceso y todo el tiempo trabaja en una ejecución normal de flujo de código síncrono.
Un buen ejemplo del comportamiento asíncrono que puede tener JavaScript son los eventos (interacción del usuario, resultados de la solicitud de Ajax, etc.) y los temporizadores, básicamente acciones que pueden ocurrir en cualquier momento.
Te recomendaría que le eches un vistazo al siguiente artículo:
Ese artículo lo ayudará a comprender la naturaleza de un solo subproceso de JavaScript y cómo los temporizadores funcionan internamente y cómo funciona la ejecución asíncrona de JavaScript.
fuente
Para alguien que realmente entiende cómo funciona JS, esta pregunta puede parecer desagradable, sin embargo, la mayoría de las personas que usan JS no tienen un nivel de conocimiento tan profundo (y no necesariamente lo necesitan) y para ellos este es un punto bastante confuso, lo haré intenta responder desde esa perspectiva.
JS es síncrono en la forma en que se ejecuta su código. cada línea solo se ejecuta después de la línea antes de que se haya completado y si esa línea llama a una función después de que se complete ect ...
El principal punto de confusión surge del hecho de que su navegador puede decirle a JS que ejecute más código en cualquier momento (similar a cómo puede ejecutar más código JS en una página desde la consola). Como ejemplo, JS tiene funciones de devolución de llamada cuyo propósito es permitir que JS SE COMPORTE de forma asíncrona para que otras partes de JS puedan ejecutarse mientras esperan que una función JS que se haya ejecutado (es decir, una
GET
llamada) devuelva una respuesta, JS continuará ejecutándose hasta el navegador tiene una respuesta en ese punto, el bucle de eventos (navegador) ejecutará el código JS que llama a la función de devolución de llamada.Dado que el bucle de eventos (navegador) puede ingresar más JS para ejecutarse en cualquier punto en ese sentido, JS es asíncrono (las cosas principales que harán que un navegador ingrese código JS son tiempos de espera, devoluciones de llamada y eventos)
Espero que esto sea lo suficientemente claro como para ser útil para alguien.
fuente
Definición
El término "asíncrono" puede usarse en significados ligeramente diferentes, lo que resulta en respuestas aparentemente conflictivas aquí, mientras que en realidad no lo son. Wikipedia en Asynchrony tiene esta definición:
el código que no es JavaScript puede poner en cola tales eventos "externos" en algunas de las colas de eventos de JavaScript. Pero eso es lo más lejos que llega.
Sin preempresión
No hay interrupción externa al ejecutar código JavaScript para ejecutar algún otro código JavaScript en su script. Las piezas de JavaScript se ejecutan una tras otra, y el orden está determinado por el orden de los eventos en cada cola de eventos y la prioridad de esas colas.
Por ejemplo, puede estar absolutamente seguro de que ningún otro JavaScript (en el mismo script) se ejecutará mientras se ejecuta el siguiente código:
En otras palabras, no hay preferencia en JavaScript. Sea lo que sea que esté en las colas de eventos, el procesamiento de esos eventos tendrá que esperar hasta que dicho código se haya completado. La especificación EcmaScript dice en la sección 8.4 Trabajos y colas de trabajos :
Ejemplos de asincronía
Como otros ya han escrito, hay varias situaciones en las que la asincronía entra en juego en JavaScript, y siempre involucra una cola de eventos, que solo puede resultar en la ejecución de JavaScript cuando no se ejecuta otro código JavaScript:
setTimeout()
: el agente (por ejemplo, el navegador) colocará un evento en una cola de eventos cuando haya expirado el tiempo de espera. La supervisión del tiempo y la ubicación del evento en la cola se realiza mediante código que no es JavaScript, por lo que puede imaginar que esto sucede en paralelo con la ejecución potencial de algún código JavaScript. Pero la devolución de llamada proporcionada asetTimeout
solo se puede ejecutar cuando el código JavaScript que se está ejecutando actualmente se ha completado y se está leyendo la cola de eventos adecuada.fetch()
: el agente utilizará las funciones del sistema operativo para realizar una solicitud HTTP y monitorear cualquier respuesta entrante. Nuevamente, esta tarea que no es JavaScript puede ejecutarse en paralelo con algún código JavaScript que aún se está ejecutando. Pero el procedimiento de resolución de la promesa, que resolverá la promesa devuelta porfetch()
, solo puede ejecutarse cuando el JavaScript que se está ejecutando actualmente se ha completado.requestAnimationFrame()
: el motor de representación del navegador (que no sea JavaScript) colocará un evento en la cola de JavaScript cuando esté listo para realizar una operación de pintura. Cuando se procesa el evento de JavaScript, se ejecuta la función de devolución de llamada.queueMicrotask()
: coloca inmediatamente un evento en la cola de microtask. La devolución de llamada se ejecutará cuando la pila de llamadas esté vacía y ese evento se consuma.Hay muchos más ejemplos, pero todas estas funciones son proporcionadas por el entorno host, no por el núcleo de EcmaScript. Con el núcleo de EcmaScript, puede colocar sincrónicamente un evento en una cola de trabajos de Promise con
Promise.resolve()
.Construcciones de lenguaje
EcmaScript proporciona varias construcciones de lenguaje para apoyar el patrón asincronía, tales como
yield
,async
,await
. Pero no se equivoque: ningún código externo será interrumpido por un evento externo. La "interrupción" queyield
yawait
parece ofrecer es sólo una manera controlada, predefinido de regresar de una llamada de función y la restauración de su contexto de ejecución más adelante, ya sea por código JS (en el caso deyield
), o la cola de eventos (en el caso deawait
)Manejo de eventos DOM
Cuando el código JavaScript accede a la API DOM, esto puede en algunos casos hacer que la API DOM active una o más notificaciones sincrónicas. Y si su código tiene un controlador de eventos escuchando eso, se llamará.
Esto puede parecer una concurrencia preventiva, pero no es así: una vez que su (s) controlador (es) de eventos devuelve (n), la API DOM eventualmente también regresará y el código JavaScript original continuará.
En otros casos, la API DOM solo enviará un evento en la cola de eventos apropiada, y JavaScript lo recogerá una vez que la pila de llamadas se haya vaciado.
Ver eventos sincrónicos y asincrónicos
fuente
Es sincrónico en todos los casos.
Ejemplo de bloqueo de hilo con
Promises
:El resultado será:
fuente