{"id":3566,"date":"2018-11-11T18:49:29","date_gmt":"2018-11-11T18:49:29","guid":{"rendered":"http:\/\/pensemosweb.com.mx\/index.php\/2018\/11\/11\/javascript-event-loop-concurrencia-asincrono\/"},"modified":"2024-04-14T16:38:25","modified_gmt":"2024-04-14T22:38:25","slug":"javascript-event-loop-concurrencia-asincrono","status":"publish","type":"post","link":"https:\/\/pensemosweb.com\/en\/javascript-event-loop-concurrencia-asincrono\/","title":{"rendered":"Javascript Event Loop, concurrencia y as\u00edncrono"},"content":{"rendered":"<h2 class=\"wp-block-heading\">Javascript es secuencial<\/h2>\n\n\n\n<p>&#8220;Event loop&#8221;, tal vez lo has escuchado. Esto es porque javascript tiene modelo de ejecuci\u00f3n de c\u00f3digo donde utiliza un ciclo de eventos (event loop), que una vez entendiendo su funcionamiento, se puede crear c\u00f3digo mucho m\u00e1s eficiente, y resolver problemas r\u00e1pidamente, que a simple vista no son tan obvios. Es la base de la concurrencia y el asincronismo.<\/p>\n\n\n\n<p>Para comenzar:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Javascript se ejecuta en un solo hilo de ejecuci\u00f3n, como se ejecuta un solo hilo, su ejecuci\u00f3n es secuencial, no es como JAVA donde se pueden lanzar otros hilos.<\/li>\n\n\n\n<li>Existen ambientes hu\u00e9spedes donde se ejecuta javascript que tienen su propia API, ejemplo:\n<ul class=\"wp-block-list\">\n<li>Navegador web<\/li>\n\n\n\n<li>Node.js<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Este funcionamiento secuencial es el mismo, no cambia por estar relacionado con un ambiente hu\u00e9sped. <\/li>\n\n\n\n<li>La concurrencia se logra a trav\u00e9s de invocaciones as\u00edncronas a la API del ambiente hu\u00e9sped, esto evita que el funcionamiento se bloquee y provoque lentitud de las aplicaciones.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Elementos para la concurrencia<\/h2>\n\n\n\n<p>Veamos con m\u00e1s detalle los elementos que hacen funcionar Javascript en los ambientes hu\u00e9spedes.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Call Stack &#8211; Pila de ejecuciones<\/li>\n\n\n\n<li>Callback Queue &#8211; Cola de retrollamadas, tambien llamado <strong>Task Queue<\/strong><\/li>\n\n\n\n<li>Event Loop &#8211; Ciclo de eventos<\/li>\n\n\n\n<li>Host Environment &#8211; Funcionalidad del ambiente hu\u00e9sped<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/2018\/11\/event-loop.jpeg\" alt=\"Event loop, ciclo de eventos javascript\" class=\"wp-image-2183\"\/><figcaption class=\"wp-element-caption\">Event loop, ciclo de eventos javascript<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Calls Stack, heap y motor de javascript<\/h3>\n\n\n\n<p>Del lado izquierdo tenemos al <strong>motor de javascript<\/strong>, este motor se encarga de ejecutar nuestro c\u00f3digo. A veces es llamado m\u00e1quina virtual, porque se encarga de interpretar nuestro c\u00f3digo a lenguaje m\u00e1quina y ejecutarlo.  Solo puede ejecutar una l\u00ednea de c\u00f3digo a la vez. Tiene un <strong>Heap <\/strong>para guardar objetos y dem\u00e1s datos en memoria que el c\u00f3digo pueda generar.<\/p>\n\n\n\n<p>Pero tambi\u00e9n tenemos una Pila de llamadas (<strong>Call Stack<\/strong>). Los elementos de la pila son objetos y datos de memoria, pero tienen una estructura especifica. Tienen un orden y el \u00faltimo elemento en entrar es el primero en salir, se le llama <strong>LIFO<\/strong> (Last-in, First-out).<\/p>\n\n\n\n<p>Cada elemento de la pila es un trozo de c\u00f3digo Javascript y guarda las referencias del contexto y variables utilizadas. La pila ejecuta el trozo de c\u00f3digo en turno hasta quedar vac\u00eda.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Callbacks Queue<\/h3>\n\n\n\n<p>Abajo tenemos <strong>Callbacks Queue,<\/strong> es una estructura de datos y guarda pedazos de c\u00f3digo que el motor de javascript puede ejecutar. Es una cola, y como la cola de las tortillas el primero en formarse, es el primero en salir (FIFO, First-in, First-out).<\/p>\n\n\n\n<p>Un <strong>callback<\/strong>, es una <a href=\"https:\/\/pensemosweb.com\/en\/introduccion-javascript\/#Funciones\">funci\u00f3n<\/a> que se pasa por par\u00e1metro a otra, de tal manera que esta \u00faltima ejecuta el callback en un punto determinado, cuando las condiciones y\/o los datos cumplen una cierta regla de invocaci\u00f3n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Event loop<\/h3>\n\n\n\n<p><strong>Event Loop<\/strong>, este elemento nos permite mover la siguiente callback del <strong>Callbacks Queue <\/strong> al <strong>Call Stack<\/strong>. Como es un ciclo, en cada iteraci\u00f3n toma un solo callback.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ambiente hu\u00e9sped<\/h3>\n\n\n\n<p>Del lado derecho tenemos <strong>El ambiente hu\u00e9sped<\/strong>, el ambiente hu\u00e9sped es el lugar donde corremos Javascript, los m\u00e1s comunes son el <strong>Navegador web <\/strong>and <strong>Node.js<\/strong>. Las tareas que ejecuta el ambiente hu\u00e9sped son independientes de los dem\u00e1s componentes. En el navegador web tiene sus propias API como fetch, setTimeout, alert. Node.js tambi\u00e9n cuenta con su propia API como net, path, crypto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfC\u00f3mo es posible?,  \u00bfY la concurrencia? \u00bfPuedo hacer muchas cosas a la vez en un sitio web?<\/h2>\n\n\n\n<p>Todo el trabajo de poner un temporizador, renderizar contenido como texto, im\u00e1genes, animaciones, o ver videos, est\u00e1n a cargo del ambiente huesped. Lo que pasa es que las APIs del navegador web generan <strong>callbacks <\/strong>cuando su tarea ya est\u00e1 completada y los agrega al <strong>Callbacks Queue&nbsp;<\/strong>para que el <strong>event loop <\/strong>las tome y las mueva al <strong>Call<\/strong> <strong>stack<\/strong>. <\/p>\n\n\n\n<p>Javascript se comunica con el ambiente hu\u00e9sped a trav\u00e9s de su API, mas adelante vamos a utilizar un ejemplo basado en el diagrama de arriba, donde se utiliza <code>window.setTimeout<\/code>, la cual es una funci\u00f3n del navegador web.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Concurrencia<\/h2>\n\n\n\n<p><strong>Home <\/strong>es la funci\u00f3n principal, con la que se inicia el proceso de ejecuci\u00f3n en el <strong>call stack<\/strong>. Dentro de inicio tenemos cuatro <strong>setTimeout <\/strong>de dos segundos. La funci\u00f3n setTimeout es propia del ambiente hu\u00e9sped, y a los cuatro setTimeouts le pasamos un callback, estos son, cb1, cb2, cb3 y cb4. &nbsp;<\/p>\n\n\n\n<p>Los temporizadores setTimeout se ejecutan en la parte de la funcionalidad del <strong>ambiente hu\u00e9sped<\/strong> dejando tiempo de ejecuci\u00f3n para el <strong>call stack<\/strong>. He aqu\u00ed la concurrencia, mientras el ambiente hu\u00e9sped ejecuta un temporizador, el <strong>call stack<\/strong> puede continuar ejecutando c\u00f3digo.<\/p>\n\n\n\n<p>Despu\u00e9s de los primeros dos segundos, el ambiente hu\u00e9sped, a trav\u00e9s del primer setTimeout pasa <code>cb1<\/code><strong>&nbsp;<\/strong>al <strong>callback queue<\/strong>, pero durante estos dos segundos se pueden realizar otras operaciones en el ambiente hu\u00e9sped, en el caso del navegador, un ejemplo seria que el usuario puede seguir escribiendo dentro de un textarea. De nuevo, he aqu\u00ed la concurrencia.<\/p>\n\n\n\n<p>Tras el primer setTimeout, el segundo setTimeout pasa <code>cb2<\/code><strong>&nbsp;<\/strong>al <strong>callback queue<\/strong> y as\u00ed sucesivamente hasta el <code>cb4<\/code>. Mientras los callbacks se pasan al <strong>callback queue<\/strong>. He <strong>event loop <\/strong>nunca deja de funcionar, por lo que en alguna iteraci\u00f3n el <strong>event Loop<\/strong> pasa <code>cb1<\/code><strong>&nbsp;<\/strong>al <strong>call stack <\/strong>y se empieza a ejecutar el c\u00f3digo de <code>cb1<\/code><strong>&nbsp;<\/strong>y esto mismo sucede con <code>cb2<\/code>, <code>cb3<\/code> and <code>cb4<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Event loop en acci\u00f3n<\/h2>\n\n\n\n<p>Aqu\u00ed abajo esta el ejemplo del que hablamos, el temporizador genera los callbacks en el orden que aparecen los setTimeouts m\u00e1s dos segundos. El <strong>Event Loop&nbsp;<\/strong>toma un callback en cada iteraci\u00f3n, por lo que cada <strong>cb <\/strong>de setTimeout se invocan uno despu\u00e9s del otro, y no exactamente despu\u00e9s de dos segundos, pues entre que se posicionan los callbacks en la cola y se mueven al <strong>call<\/strong> <strong>stack<\/strong> de ejecuci\u00f3n transcurre m\u00e1s tiempo. Esto sin contar el tiempo que trascurre entre cada invocaci\u00f3n de setTimeout.<\/p>\n\n\n\n<figure class=\"kg-card kg-embed-card\"><iframe id=\"cp_embed_vejvQa\" class=\"cp_embed_iframe\" style=\"width: 100%; overflow: hidden;\" title=\"JS: Concurrencia y event loop\" src=\"https:\/\/codepen.io\/jaime_cervantes_ve\/embed\/preview\/vejvQa?height=300&#038;slug-hash=vejvQa&#038;default-tabs=js,result&#038;host=https:\/\/codepen.io\" height=\"300\" frameborder=\"0\" scrolling=\"no\"><\/iframe><\/figure>\n\n\n\n<p>Si en los cuatro callbacks se indica el mismo tiempo en milisegundos. Presiona el bot\u00f3n <strong>RERUN, <\/strong>Te dar\u00e1s cuenta de que los tiempos no son iguales y que pueden pasar m\u00e1s de dos segundos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Las APIs hu\u00e9spedes reciben <strong>callbacks&nbsp;<\/strong>que deben insertar en la<strong> callback queue <\/strong>cuando el trabajo que se les encomienda esta hecho, por ejemplo un callback de una <strong>petici\u00f3n ajax&nbsp;<\/strong>se pasa a la <strong>callback queue<\/strong> solo cuando la petici\u00f3n ya obtuvo la respuesta. En el ejemplo que describimos arriba con <strong>setTimeout<\/strong>, cuando pasan dos segundos, se inserta el callback al <strong>callback queue<\/strong>. <\/li>\n\n\n\n<li>Mientras el ambiente hu\u00e9sped realiza sus tareas, en este caso, los dem\u00e1s temporizadores, el <strong>call stack&nbsp;<\/strong>de ejecuci\u00f3n de javascript puede ejecutar el c\u00f3digo que el <strong>event loop<\/strong> le puede pasar desde el <strong>callback queue<\/strong>.<\/li>\n\n\n\n<li>He <strong>Event loop&nbsp;<\/strong>es un ciclo infinito que mientras existan callbacks en el callback queue, pasara cada callback, uno por uno, al <strong>call stack<\/strong>.<\/li>\n\n\n\n<li>He <strong>call stack&nbsp;<\/strong>no puede ejecutar m\u00e1s de un c\u00f3digo a la vez, va ejecutando desde el \u00faltimo elemento hasta el primero, en nuestro caso hasta la terminaci\u00f3n de la funci\u00f3n <strong>inicio&nbsp;<\/strong>que dio origen a todo el proceso. Es una estructura de datos tipo Pila.<\/li>\n<\/ol>\n\n\n\n<p>Gracias a que los callbacks se ejecutan hasta que un trabajo espec\u00edfico est\u00e9 terminado, proporciona una manera as\u00edncrona de ejecutar tareas. Las tareas pueden realizarse en el ambiente hu\u00e9sped sin afectar la ejecuci\u00f3n del <strong>call stack<\/strong>. En la pila solo se ejecuta c\u00f3digo que recibe el resultado de las tareas realizadas por el ambiente hu\u00e9sped.<\/p>","protected":false},"excerpt":{"rendered":"<p>        Javascript es secuencial y solo se puede ejecutar una l\u00ednea de c\u00f3digo a la vez, entonces, \u00bfC\u00f3mo puedo hacer muchas cosas al mismo tiempo en un sitio web?<\/p>","protected":false},"author":2,"featured_media":3736,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[28,30],"tags":[54,64,68],"class_list":["post-3566","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","category-node-js","tag-javascript","tag-node-js","tag-intermedio"],"_links":{"self":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/3566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/comments?post=3566"}],"version-history":[{"count":3,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/3566\/revisions"}],"predecessor-version":[{"id":3913,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/3566\/revisions\/3913"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/media\/3736"}],"wp:attachment":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/media?parent=3566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/categories?post=3566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/tags?post=3566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}