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).
- ¿Cuáles son las diferencias significativas entre el prototipo y el producto real (aplicación web)?
- ¿Cuáles son las cosas más importantes que debemos tener en cuenta para mantener segura la API web para una aplicación de Android?
- ¿Cuáles son los 4 componentes más importantes de una aplicación web desde la perspectiva del usuario?
- ¿Necesito aprender HTML CSS y JavaScript para crear una aplicación web?
- Cómo escribir un informe de prueba de penetración web
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).