¿Node.js tiene más de 1 bucle de eventos / cola de tareas?

Si quieres una respuesta rápida, ve al final , pero si tienes curiosidad sobre cómo funcionan las implementaciones de JS, aquí vamos …

En el front-end, el entorno JavaScript es proporcionado por:

  • el motor central JS (ChakraCore, V8, JavaScriptCore, SpiderMonkey, Rhino, Narwhal, …)
  • el motor “web” (Trident, EdgeHTML, Blink, WebCore, Gecko, …)

Estos son los que se usan en los navegadores más populares como Microsoft Edge (EdgeHTML / ChakraCore), Google Chrome & Opera (Blink / V8), Mozilla Firefox (Gecko / SpiderMonkey) y Apple Safari (WebCore / JavaScriptCore).

Bucle de eventos vs tareas / devolución de llamada / colas de trabajos

Tenga en cuenta, para ser claros, que una cola de tareas es solo un componente en un bucle de eventos y que el motor puede implementar colas de tareas sin “bucles” de eventos.

La cola de tareas es como una lista de “scripts”, “expresiones” o “devoluciones de llamada” para llamar en un orden específico.

Es solo desde ECMAScript 6 que se requieren implementaciones de JavaScript centrales para crear “colas de trabajos”. Deben implementar al menos 2 de ellos: ” ScriptJobs ” para manejar los módulos es6 y ” PromiseJobs ” para Promises (sin cambios en ES 7.0). Pero no hay evento de bucle.

ver trabajos y colas de trabajos de EcmaScript 6.0

El bucle de eventos, en este lado, es un bucle interminable que ejecuta los “trabajos” que están en su propia cola.

Algunos eventos agregan algunas tareas a esta cola de bucle de eventos. Si es así, lanzará estos oyentes / devoluciones de llamada adicionales una vez que ya no haya más esperando en su cola.

Una charla bastante interesante sobre este tema es esta: ¿Qué diablos es el ciclo de eventos de todos modos? impartido por Philip Roberts en JSConf.eu 2014.

motor central JS

El motor central JS implementa el estándar ECMAScript (también conocido como ECMA-262 ).

El estándar ECMAScript, a partir de hoy, no define ningún modelo de concurrencia. No define JavaScript como un lenguaje asincrónico.

Por cierto, JavaScript también se usa en implementaciones basadas en subprocesos múltiples como JS .NET, Ringo.js (usando rhino), TeaJS, Common Node o Wakanda.

Hubo una discusión hace 6 años para incluir setTimeout() y setInterval() (del W3C / WHATWG Temporizadores HTML5 ) en ECMAScript (consulte Traer setTimeout a ECMAScript) pero todavía no está disponible hasta el día de hoy.

Aquí alguien recientemente (nov. 2016) preguntó cómo implementarlo en V8:
V8-Grupos de usuarios de Google

ECMAScript comenzó, desde ES2015 (también conocido como ES6 ) para agregar API asíncronas relacionadas como Promesas y Generadores (mejor definidos en ES2016) y ES2017 (también conocido como ES8) debería venir con las Funciones Asíncronas. Pero, las devoluciones de llamada de Generator y Promise son llamadas manualmente por el código JS del usuario a través de yield , next() , resolve() y reject() , al igual que getter / setters en propiedades de objetos y objetos proxy. Entonces, no se requiere ningún bucle de eventos aquí. Las promesas solo necesitan mantener una “cola de trabajo” porque puede establecer múltiples devoluciones de llamada a través de sus métodos then() y catch() .

Incluso podría tener un EventEmitter on() / emit emit() o DOM Events addEventListener() / dispatch() , siempre y cuando todos los eventos se envíen / emitan manualmente por código de usuario, todo lo que se requiere son esas colas de devolución de llamada API, sin bucles de eventos .

V8 y otros motores JS no implementan API de E / S que requieran un bucle de eventos .

Motor “web”

Este implementa los estándares web como la API DOM, la API BOM, XMLHttpRequest y muchos más. Estos estándares están definidos por el W3C o WHATWG, o ambos.

Debido a que, por razones históricas, JavaScript inicialmente solo se ejecutaba en un solo subproceso que también tiene la tarea de representar la interfaz de usuario, la mayoría de estos estándares depende de API asíncronas basadas en el estándar de “Evento DOM”. Esos eventos son enviados por procesos que no son ejecutados por el intérprete JS y que pueden ser muy externos al DOM (cf XMLHttpRequest ). Es por eso que se ha integrado un bucle de eventos al motor web . Cuando ocurre un evento externo, el bucle lo envía al motor JS para que inicie la cola de tareas relacionadas.

JavaScript del lado del servidor

JavaScript se ejecuta en el servidor desde 1997 en el servidor Netscape Enterprise y 1998 en Microsoft IIS , luego también en cualquier plataforma Java a través de Mozilla Rhino .

El JS del lado del servidor comenzó a obtener popularidad pública en 2008 cuando Aptana , que era popular por su estudio de desarrollo JS / HTML, propuso su nueva solución de servidor js llamada Jaxer basada en SpiderMonkey + Gecko (también hizo que la API DOM estuviera disponible en el servidor). John Resig (autor de jQuery) se unió a la Junta de Aptana y lo promovió en una publicación de blog: JavaScript del lado del servidor con Jaxer

En ese momento, JavaScript comenzó a considerarse como un lenguaje más serio que en el pasado, por lo que comenzó a llamar más la atención sobre el uso del servidor.

El grupo de trabajo ServerJS se creó para convertirse finalmente en el grupo de trabajo CommonJS que definió una lista de propuestas API comunes (cliente / servidor) como módulos CommonJS, paquetes, pruebas unitarias, pero también archivos, flujo de E / S y otras API.

En 2009, se realizaron 3 presentaciones en conferencias de JS:

  • Estándares CommonJS
  • Servidor Wakanda (utilizaba WebKit JavaScriptCore, también conocido como SquirelFish, pero se mudó a V8 una vez que también se convirtió en 64 bits / multihilo / seguro para subprocesos)
  • node.js (el V8 usado desde el inicio inicialmente solo requería 1 subproceso)

node.js tiene mucha atracción debido a 2 cosas:

  • fue muy ligero
  • propuso introducir el bucle de eventos JS front-end en el servidor

No me malinterpreten, ya había muchas soluciones existentes basadas en eventos en el servidor, pero era mucho más “popular” en JavaScript, que era el único lenguaje que ya se usaba en casi todos los proyectos web modernos.

Multi-bucles de eventos

Ahora, lo que debe tener en cuenta es que generalmente solo tendrá “un” bucle de eventos por “Contexto JS” y un “Contexto JS” por hilo (o en algún momento incluso por proceso)

En el front-end puede crear tantos contextos JS o contextos web (incrustando su propio contexto JS) como desee usando:

  • (o incluso y para navegadores muy antiguos)
  • windows (a través de window.open() )
  • o Web Workers (APIs JS Context + Worker Global puras)

Nota: la primera sala de chat que escribí en JavaScript estaba usando contextos de marco. En ese momento, XMLHttpRequest aún no existía, pero ya era posible comunicarse entre cuadros y usar uno para cargar datos nuevos.

En las aplicaciones nativas , puede usar API nativas para crear contextos JS centrales, pero no tendrán un bucle de eventos de forma predeterminada mientras que los Contextos web creados (aún a través de API nativas) lo tendrán. Cordova crea un contexto web a través de API nativas, por lo que obtendrá el bucle de eventos del motor web. NativeScript y React Native crean solo contextos JS y luego tienen que manejar los eventos por su cuenta .

En el back-end:

  • en RingoJS o Wakanda, tendrá por defecto un hilo por solicitud HTTP y no proporcionarán ningún bucle de eventos.
  • Wakanda aún le permite a la API de Web Worker crear contextos JS dedicados y compartidos + una forma de crear hilos node.js con sus propios contextos JS. También le permite crear manejadores WebSocket a través de trabajadores dedicados o compartidos.
  • node.js proporciona un proceso secundario y una API de clúster. Ambos te permiten crear nuevos contextos JS con sus propios bucles de eventos.

ASI QUE

¿Node.js tiene más de 1 bucle de eventos / cola de tareas?

Cada instancia de Node.js EventEmitter (por ejemplo, net.Server , fs.ReadStream , …) maneja una cola de tareas por tipo de evento. Entonces tienes muchas colas de tareas 😉

EventEmitter se implementa en JS puro: nodejs / node / lib / events.js

Con respecto a los bucles de eventos, node.js puede tener más de uno a través del proceso secundario mencionado o las API de clúster, pero generalmente solo usa 1 bucle de eventos en su hilo principal predeterminado.

¿Este bucle de eventos reemplaza al que normalmente vemos en el front-end, o este nuevo bucle de eventos complementa al del front-end?

  • Los bucles de eventos Node.js se ejecutan sobre contextos Server Core JS a través de libuv.
  • Los bucles de eventos front-end se ejecutan en contextos web del cliente y contexto JS del trabajador a través de un motor web.

Por lo tanto, el bucle de eventos principal de node.js (+ potencialmente otros procesos de nodo) complementa el bucle de eventos de contexto web de la página principal de front-end (y potencialmente otros de front-end).

No estoy totalmente seguro de lo que está preguntando, pero NodeJs se ejecuta en el lado del servidor y su sitio web se ejecuta en el lado del cliente. Cada uno ejecuta sus propios bucles pares, generalmente en máquinas diferentes. Tienen muy poco acoplamiento. De hecho, el lado del cliente puede no tener ningún bucle de eventos de JavaScript, el servidor generalmente solo está ofreciendo respuestas REST que pueden ser consumidas por cualquier tipo de cliente, ya sea un navegador que ejecuta JavaScript o una aplicación C ++.

En cualquier caso, puede tener múltiples bucles de eventos en su servidor de nodo, cada uno iniciado en su propio proceso. Sin embargo, no tiene hilos, pero tiene varias formas de lograr la concurrencia que generalmente son más fáciles de implementar y pueden ser más eficaces cuando se utilizan para el tipo correcto de tareas, como servir contenido web. Lea esto, es una introducción rápida sobre la concurrencia de NodeJs.

¿Cuál sería mejor para tareas concurrentes en node.js? Fibras? ¿Trabajadores web? o hilos?

Utilice el método de cola asíncrona de nodo.

Implementar cola utilizando el nodo Módulo JS Async Ejemplo

More Interesting

¿Cuál es el mejor enfoque para la arquitectura de una aplicación de una sola página (cargando a través del servidor o el cliente)?

¿Cuál es el mejor conversor de PDF a HTML?

¿Cuáles son las cosas que necesito aprender para hacer aplicaciones web?

¿Cuál es una buena alternativa a la Lista de tareas pendientes de Basecamp?

¿Cómo surgió la primera aplicación JavaScript de una sola página?

¿Existen buenas aplicaciones web de código abierto (preferiblemente basadas en LAMP) para crear cuestionarios de autoidentificación política?

¿Existen bases de datos distribuidas disponibles gratuitamente que estén diseñadas para escalar a miles de millones de usuarios en tiempo real? Si es así, ¿Que son?

¿Cuál es el requisito de hardware (infraestructura) necesario para que Jmeter cargue grandes aplicaciones web de prueba? (Digamos, sitios web y aplicaciones de la universidad).

¿Cuál es la diferencia de velocidad entre el agente de usuario web y la detección de características?

¿Qué empresa debo contratar para el desarrollo web para mi startup?

¿Qué opciones hay para implementar el reconocimiento de imágenes en una aplicación web?

Outsourcing a India: ¿Por qué un desarrollador sénior tarda de 4 a 10 veces más en implementar la misma función que un desarrollador del primer mundo?

Cómo medir mi ROI después de invertir en un nuevo sitio web

¿Cuáles son las precauciones antes de poner en funcionamiento mi aplicación web?

¿Cómo llegó Pinterest a más de 10 millones de usuarios?