¿Qué es Node.js? [cerrado]

506

No entiendo completamente de qué se trata Node.js. Tal vez sea porque soy principalmente un desarrollador de aplicaciones de negocios basado en la web. ¿Qué es y para qué sirve?

Mi comprensión hasta ahora es que:

  1. El modelo de programación es dirigido por eventos, especialmente por la forma en que maneja E / S .
  2. Utiliza JavaScript y el analizador es V8 .
  3. Se puede usar fácilmente para crear aplicaciones de servidor concurrentes.

¿Son correctos mis entendimientos? En caso afirmativo, ¿cuáles son los beneficios de la E / S desarrollada? ¿Es solo algo más para las cosas de concurrencia? Además, ¿es la dirección de Node.js convertirse en un modelo de programación basado en JavaScript (basado en V8)?

Jeff
fuente

Respuestas:

213

Creo que las ventajas son:

  1. Desarrollo web en un lenguaje dinámico (JavaScript) en una VM que es increíblemente rápido (V8). Es mucho más rápido que Ruby, Python o Perl.

  2. Capacidad para manejar miles de conexiones concurrentes con una sobrecarga mínima en un solo proceso.

  3. JavaScript es perfecto para bucles de eventos con objetos de función y cierres de primera clase. La gente ya sabe cómo usarlo de esta manera al usarlo en el navegador para responder a eventos iniciados por el usuario.

  4. Mucha gente ya conoce JavaScript, incluso las personas que no afirman ser programadores. Es posiblemente el lenguaje de programación más popular.

  5. El uso de JavaScript en un servidor web y en el navegador reduce la falta de coincidencia de impedancia entre los dos entornos de programación que pueden comunicar estructuras de datos a través de JSON que funcionan igual en ambos lados de la ecuación. El código de validación de formulario duplicado se puede compartir entre el servidor y el cliente, etc.

postfuturista
fuente
1
@postfuturist: Realmente funciona bien contra muchas alternativas. También supera a Java 6 de manera bastante práctica en muchos casos. ¡Ordenado!
Adam Crossland
1
@postfuturist Creo que lo has comparado con java 6 -Xint. Intente comparar con java 6 -server
fedesilva
@iJK yammer.com es una aplicación funcional de node.js
Gerard Banasig
1
Es curioso que escribí JScript en ASP hace 10 años para poder (a) evitar lo horrible de VBScript, (b) usar el mismo lenguaje en el cliente y el servidor, y (c) reutilizar las bibliotecas JS propias y de otros para manejo de cuerdas ... etc.
Antony Quinn
44
@ ¿Por qué editó esta publicación solo para "Legacy bullshit"? No creo que 212 personas hubieran votado por esta publicación si escribieras esto desde el principio.
Julien Fouilhé
619

Yo uso Node.js en el trabajo, y encuentro que es muy poderoso. Obligado a elegir una palabra para describir Node.js, diría "interesante" (que no es un adjetivo puramente positivo). La comunidad es vibrante y en crecimiento. JavaScript, a pesar de sus rarezas, puede ser un gran lenguaje para codificar. Y diariamente repensará su propia comprensión de la "mejor práctica" y los patrones de código bien estructurado. En este momento hay una enorme energía de ideas que fluye hacia Node.js, y trabajar en él te expone a todo este pensamiento: un gran levantamiento de pesas mental.

Node.js en producción es definitivamente posible, pero lejos de la implementación "llave en mano" aparentemente prometida por la documentación. Con Node.js v0.6.x, "cluster" se ha integrado en la plataforma, proporcionando uno de los bloques de construcción esenciales, pero mi script "production.js" sigue siendo ~ 150 líneas de lógica para manejar cosas como crear el registro directorio, reciclaje de trabajadores muertos, etc. Para un servicio de producción "serio", también debe estar preparado para limitar las conexiones entrantes y hacer todo lo que hace Apache para PHP . Para ser justos, Ruby on Rails tiene este problema exacto . Se resuelve mediante dos mecanismos complementarios: 1) Poner Ruby on Rails / Node.Apache / Lighttd ). El servidor web puede servir eficientemente contenido estático, acceder al registro, reescribir URL, terminar SSL , aplicar reglas de acceso y administrar múltiples sub-servicios. Para las solicitudes que llegan al servicio de nodo real, el servidor web envía la solicitud a través de proxy. 2) Utilizando un marco como Unicorn que gestionará los procesos de los trabajadores, los reciclará periódicamente, etc. Todavía no he encontrado un marco de servicio Node.js que parezca completamente horneado; puede existir, pero aún no lo he encontrado y todavía uso ~ 150 líneas en mi "production.js" enrollado a mano.

Leer marcos como Express hace que parezca que la práctica estándar es simplemente servir todo a través de un servicio Node.js de Jack-of-all-trades ... "app.use (express.static (__ dirname + '/ public'))" . Para servicios y desarrollo de menor carga, probablemente esté bien. Pero tan pronto como intente poner una gran carga en su servicio y hacer que funcione las 24 horas, los 7 días de la semana, descubrirá rápidamente las motivaciones que impulsan a los sitios grandes a tener un código C bien horneado y endurecido como Nginx al frente de su sitio y manejando todo de las solicitudes de contenido estático (... hasta que configure un CDN , como Amazon CloudFront )). Para una versión algo humorística y descaradamente negativa de esto, vea a este chico .

Node.js también está encontrando más y más usos que no son de servicio. Incluso si está usando algo más para servir contenido web, aún puede usar Node.js como herramienta de compilación, usar módulos npm para organizar su código, Browserify para unirlo en un solo activo y uglify-js para minimizarlo para la implementación . Para tratar con la web, JavaScript es una combinación perfecta de impedancia y, con frecuencia, es la ruta de ataque más fácil. Por ejemplo, si desea avanzar a través de un montón de cargas útiles de respuesta JSON , debe usar mi módulo subrayado-CLI , el cinturón de utilidades de datos estructurados.

Pros contras:

  • Pro: Para un servidor, escribir JavaScript en el back-end ha sido una "droga de entrada" para aprender patrones modernos de IU. Ya no temo escribir código de cliente.
  • Pro: tiende a fomentar la comprobación de errores adecuada (prácticamente todas las devoluciones de llamada devuelven err, lo que molesta al programador para que lo maneje; también, async.js y otras bibliotecas manejan el paradigma de "falla si alguna de estas subtareas falla" mucho mejor que el código síncrono típico )
  • Pro: algunas tareas interesantes y normalmente difíciles se vuelven triviales, como obtener el estado de las tareas en vuelo, comunicarse entre los trabajadores o compartir el estado de la memoria caché
  • Pro: gran comunidad y toneladas de excelentes bibliotecas basadas en un sólido administrador de paquetes (npm)
  • Con: JavaScript no tiene una biblioteca estándar. Te acostumbras tanto a importar la funcionalidad que se siente extraño cuando usas JSON.parse o algún otro método integrado que no requiere agregar un módulo npm. Esto significa que hay cinco versiones de todo. Incluso los módulos incluidos en el "núcleo" de Node.js tienen cinco variantes más si no está satisfecho con la implementación predeterminada. Esto lleva a una rápida evolución, pero también a cierto nivel de confusión.

Frente a un modelo simple de un proceso por solicitud ( LAMP ):

  • Pro: escalable a miles de conexiones activas. Muy rápido y muy eficiente. Para una flota web, esto podría significar una reducción de 10 veces en el número de cajas requeridas en comparación con PHP o Ruby
  • Pro: Escribir patrones paralelos es fácil. Imagine que necesita obtener tres (o N) blobs de Memcached . Haz esto en PHP ... ¿acabas de escribir código para obtener el primer blob, luego el segundo y luego el tercero? Wow, eso es lento. Hay un módulo PECL especial para solucionar ese problema específico de Memcached, pero ¿qué sucede si desea obtener algunos datos de Memcached en paralelo con la consulta de su base de datos? En Node.js, debido a que el paradigma es asíncrono, es muy natural que una solicitud web haga varias cosas en paralelo.
  • Con: el código asincrónico es fundamentalmente más complejo que el código síncrono, y la curva de aprendizaje inicial puede ser difícil para los desarrolladores sin una comprensión sólida de lo que realmente significa la ejecución concurrente. Aún así, es mucho menos difícil que escribir cualquier tipo de código multiproceso con bloqueo.
  • Con: si se ejecuta una solicitud de cálculo intensivo durante, por ejemplo, 100 ms, detendrá el procesamiento de otras solicitudes que se están manejando en el mismo proceso Node.js ... AKA, cooperativo-multitarea . Esto se puede mitigar con el patrón Trabajadores web (derivando un subproceso para lidiar con la tarea costosa). Alternativamente, podría usar una gran cantidad de trabajadores de Node.js y solo dejar que cada uno maneje una sola solicitud al mismo tiempo (aún bastante eficiente porque no hay proceso de reciclaje).
  • Con: Ejecutar un sistema de producción es MUCHO más complicado que un modelo CGI como Apache + PHP, Perl , Ruby , etc. Las excepciones no controladas derribarán todo el proceso, lo que requiere lógica para reiniciar los trabajadores fallidos (ver clúster ). Los módulos con código nativo con errores pueden bloquear el proceso. Cada vez que un trabajador muere, cualquier solicitud que maneja se descarta, por lo que una API con errores puede degradar fácilmente el servicio para otras API cohospedadas.

Versus escribir un servicio "real" en Java / C # / C (C? ¿Realmente?)

  • Pro: Hacer asíncrono en Node.js es más fácil que hacer seguridad de subprocesos en cualquier otro lugar y podría proporcionar un mayor beneficio. Node.js es, con mucho, el paradigma asincrónico menos doloroso en el que he trabajado. Con buenas bibliotecas, es solo un poco más difícil que escribir código sincrónico.
  • Pro: Sin errores de subprocesamiento / subprocesamiento múltiple. Es cierto que invierte por adelantado en escribir código más detallado que exprese un flujo de trabajo asincrónico adecuado sin operaciones de bloqueo. Y necesita escribir algunas pruebas y hacer que funcione (es un lenguaje de script y los nombres de variables de digitación gorda solo se detectan en el momento de la prueba de la unidad). PERO, una vez que lo hace funcionar, el área de superficie para errores de seguridad (problemas extraños que solo se manifiestan una vez en un millón de carreras) esa área de superficie es mucho más baja. Los impuestos que escriben el código Node.js se cargan en la fase de codificación. Entonces tiendes a terminar con un código estable.
  • Pro: JavaScript es mucho más liviano para expresar la funcionalidad. Es difícil probar esto con palabras, pero JSON , tipeo dinámico, notación lambda, herencia de prototipos, módulos livianos, lo que sea ... simplemente toma menos código para expresar las mismas ideas.
  • Con: ¿Tal vez realmente te gustan los servicios de codificación en Java?

Para obtener otra perspectiva sobre JavaScript y Node.js, consulte De Java a Node.js , una publicación de blog sobre las impresiones y experiencias de un desarrollador de Java al aprender Node.js.


Módulos Al considerar el nodo, tenga en cuenta que su elección de bibliotecas JavaScript DEFINIRÁ su experiencia. La mayoría de las personas usan al menos dos, un asistente de patrón asíncrono (Step, Futures, Async) y un módulo de azúcar JavaScript ( Underscore.js ).

Ayudante / JavaScript Sugar:

  • Underscore.js : use esto. Simplemente hazlo. Hace que su código sea agradable y legible con cosas como _.isString () y _.isArray (). No estoy realmente seguro de cómo podría escribir código seguro de lo contrario. Además, para una línea de comando-fu mejorada, consulte mi propia Underscore-CLI .

Módulos de patrones asincrónicos:

  • Paso : una forma muy elegante de expresar combinaciones de acciones en serie y paralelas. Mi recomendación personal. Vea mi publicación sobre cómo se ve el código de paso.
  • Futuros : forma mucho más flexible (¿es realmente algo bueno?) De expresar el pedido a través de los requisitos. Puede expresar cosas como "comience a, b, c en paralelo. Cuando A y B terminen, comience AB. Cuando A y C terminen, comience AC". Dicha flexibilidad requiere más cuidado para evitar errores en su flujo de trabajo (como nunca llamar a la devolución de llamada o llamarla varias veces). Vea la publicación de Raynos sobre el uso de futuros (esta es la publicación que me hizo "obtener" futuros).
  • Asíncrono : biblioteca más tradicional con un método para cada patrón. Comencé con esto antes de mi conversión religiosa a paso y posterior comprensión de que todos los patrones en Async podrían expresarse en Paso con un solo paradigma más legible.
  • TameJS : escrito por OKCupid, es un precompilador que agrega un nuevo lenguaje "aguarda" primitivo para escribir elegantemente flujos de trabajo en serie y paralelos. El patrón se ve increíble, pero requiere una compilación previa. Todavía estoy decidiéndome en este caso.
  • StreamlineJS - competidor de TameJS. Me estoy inclinando hacia Tame, pero puedes decidirte.

O para leer todo sobre las bibliotecas asíncronas, vea esta entrevista de panel con los autores.

Marco web:

  • Exprese el marco Great Ruby on Rails-esk para organizar sitios web. Utiliza JADE como un motor de plantillas XML / HTML, lo que hace que la creación de HTML sea mucho menos dolorosa, incluso elegante.
  • jQuery Aunque técnicamente no es un módulo de nodo, jQuery se está convirtiendo rápidamente en un estándar de facto para la interfaz de usuario del lado del cliente. jQuery proporciona selectores similares a CSS para 'consultar' conjuntos de elementos DOM que luego se pueden operar (controladores de conjuntos, propiedades, estilos, etc.). En la misma línea, el framework CSS Bootstrap de Twitter , Backbone.js para un patrón MVC y Browserify.js para unir todos sus archivos JavaScript en un solo archivo. Todos estos módulos se están convirtiendo en estándares de facto, por lo que al menos debería consultarlos si no ha oído hablar de ellos.

Pruebas:

  • JSHint - Debe usar; Al principio no usé esto, que ahora parece incomprensible. JSLint agrega varias verificaciones básicas que obtienes con un lenguaje compilado como Java. Paréntesis no coincidentes, variables no declaradas, tipos de muchas formas y tamaños. También puede activar varias formas de lo que yo llamo "modo anal", donde verifica el estilo de espacios en blanco y demás, lo cual está bien si esa es su taza de té, pero el valor real proviene de obtener comentarios instantáneos sobre el número de línea exacto donde olvidó un cierre ")" ... sin tener que ejecutar su código y presionar la línea ofensiva. "JSHint" es una variante más configurable de Douglas Crockford 's JSLint .
  • Mocha competidor de votos que estoy empezando a preferir. Ambos marcos manejan los conceptos básicos lo suficientemente bien, pero los patrones complejos tienden a ser más fáciles de expresar en Mocha.
  • Votos Votos es realmente bastante elegante. E imprime un informe encantador (--spec) que muestra qué casos de prueba pasaron / fallaron. Dedique 30 minutos a aprenderlo y puede crear pruebas básicas para sus módulos con un mínimo esfuerzo.
  • Zombie : prueba sin cabeza para HTML y JavaScript utilizando JSDom como un "navegador" virtual. Cosas muy poderosas. Combínelo con Replay para obtener pruebas deterministas rápidas del código en el navegador.
  • Un comentario sobre cómo "pensar en" las pruebas:
    • La prueba no es opcional. Con un lenguaje dinámico como JavaScript, hay muy pocos controles estáticos. Por ejemplo, pasar dos parámetros a un método que espera que 4 no se rompa hasta que se ejecute el código. Barra bastante baja para crear errores en JavaScript. Las pruebas básicas son esenciales para compensar la brecha de verificación con lenguajes compilados.
    • Olvídate de la validación, solo ejecuta tu código. Para cada método, mi primer caso de validación es "nada se rompe", y ese es el caso que se dispara con mayor frecuencia. Probar que su código se ejecuta sin arrojar capturas del 80% de los errores y hará tanto para mejorar la confianza de su código que se encontrará regresando y agregando los casos de validación matizados que omitió.
    • Comience con poco y rompa la barrera de inercia. Todos somos perezosos y estamos presionados por el tiempo, y es fácil ver las pruebas como "trabajo extra". Así que empieza con algo pequeño. Escriba el caso de prueba 0: cargue su módulo e informe el éxito. Si te obligas a hacer exactamente esto, entonces la barrera de inercia para las pruebas se rompe. Eso es <30 minutos para hacerlo la primera vez, incluida la lectura de la documentación. Ahora escriba el caso de prueba 1: llame a uno de sus métodos y verifique que "nada se rompa", es decir, que no reciba un error. El caso de prueba 1 debería llevarle menos de un minuto. Con la inercia desaparecida, se vuelve fácil expandir gradualmente su cobertura de prueba.
    • Ahora desarrolle sus pruebas con su código. No se deje intimidar por cómo se vería la prueba "correcta" de extremo a extremo con servidores simulados y todo eso. El código comienza simple y evoluciona para manejar nuevos casos; las pruebas también deberían hacerlo. A medida que agrega nuevos casos y nueva complejidad a su código, agregue casos de prueba para ejercer el nuevo código. A medida que encuentre errores, agregue verificaciones y / o casos nuevos para cubrir el código defectuoso. Cuando esté depurando y pierda la confianza en un fragmento de código, regrese y agregue pruebas para demostrar que está haciendo lo que cree que está haciendo. Capture cadenas de datos de ejemplo (de otros servicios que llame, sitios web que raspe, lo que sea) y aliméntelos con su código de análisis. Algunos casos aquí, validación mejorada allí, y terminarás con un código altamente confiable.

Además, consulte la lista oficial de módulos Node.js recomendados. Sin embargo, el Wiki de módulos de nodo de GitHub es mucho más completo y un buen recurso.


Para comprender Nodo, es útil considerar algunas de las opciones de diseño clave:

Node.js está BASADO EN EVENTOS y ASINCRÓNICO / SIN BLOQUEO. Los eventos, como una conexión HTTP entrante, activarán una función de JavaScript que hace un poco de trabajo y desencadena otras tareas asincrónicas como conectarse a una base de datos o extraer contenido de otro servidor. Una vez que se han iniciado estas tareas, la función de evento finaliza y Node.js vuelve a dormir. Tan pronto como sucede algo más, como la conexión de la base de datos establecida o el servidor externo respondiendo con contenido, las funciones de devolución de llamada se activan y se ejecuta más código JavaScript, lo que puede iniciar aún más tareas asincrónicas (como una consulta de base de datos). De esta manera, Node.js felizmente intercalará actividades para múltiples flujos de trabajo paralelos, ejecutando cualquier actividad que esté desbloqueada en cualquier momento. Es por eso que Node.js hace un gran trabajo al administrar miles de conexiones simultáneas.

¿Por qué no usar solo un proceso / hilo por conexión como todos los demás?En Node.js, una nueva conexión es solo una asignación de montón muy pequeña. Acelerar un nuevo proceso requiere mucha más memoria, un megabyte en algunas plataformas. Pero el costo real es la sobrecarga asociada con el cambio de contexto. Cuando tiene 10 ^ 6 hilos de kernel, el kernel tiene que hacer mucho trabajo para averiguar quién debe ejecutar a continuación. Se ha trabajado mucho en la construcción de un planificador O (1) para Linux, pero al final, es mucho más eficiente tener un solo proceso impulsado por eventos que 10 ^ 6 procesos que compiten por el tiempo de CPU. Además, en condiciones de sobrecarga, el modelo multiproceso se comporta muy mal, privando de servicios de administración y administración críticos, especialmente SSHD (lo que significa que ni siquiera puede iniciar sesión en la caja para descubrir qué tan mal está realmente).

Node.js es de UN SOLO ROSCADO y SIN BLOQUEO . Node.js, como una elección de diseño muy deliberada, solo tiene un solo hilo por proceso. Debido a esto, es fundamentalmente imposible que múltiples hilos accedan a los datos simultáneamente. Por lo tanto, no se necesitan cerraduras. Los hilos son duros. Muy, muy duro. Si no lo crees, no has hecho suficiente programación de hilos Obtener el bloqueo correcto es difícil y genera errores que son realmente difíciles de rastrear. La eliminación de bloqueos y subprocesos múltiples hace que una de las clases de errores más desagradables desaparezca. Esta podría ser la mayor ventaja del nodo.

Pero, ¿cómo aprovecho mi caja de 16 núcleos?

Dos caminos:

  1. Para grandes tareas de cómputo pesado como la codificación de imágenes, Node.js puede iniciar procesos secundarios o enviar mensajes a procesos de trabajo adicionales. En este diseño, tendría un subproceso que administra el flujo de eventos y N procesos que realizan tareas de computación pesadas y mastican las otras 15 CPU.
  2. Para escalar el rendimiento en un servicio web, debe ejecutar varios servidores Node.js en una caja, uno por núcleo, usando el clúster (con Node.js v0.6.x, el módulo oficial "clúster" vinculado aquí reemplaza la versión de learnboost que tiene una API diferente) Estos servidores locales de Node.js pueden competir en un socket para aceptar nuevas conexiones, equilibrando la carga entre ellas. Una vez que se acepta una conexión, queda estrechamente vinculada a uno solo de estos procesos compartidos. En teoría, esto suena mal, pero en la práctica funciona bastante bien y le permite evitar el dolor de cabeza de escribir código seguro para subprocesos. Además, esto significa que Node.js obtiene una excelente afinidad de caché de la CPU, utilizando más efectivamente el ancho de banda de la memoria.

Node.js te permite hacer cosas realmente poderosas sin sudar. Suponga que tiene un programa Node.js que realiza una variedad de tareas, escucha en unpuerto TCP los comandos, codifica algunas imágenes, lo que sea. Con cinco líneas de código, puede agregar un portal de administración web basado en HTTP que muestre el estado actual de las tareas activas. Esto es fácil de hacer:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");

Ahora puede presionar una URL y verificar el estado de su proceso en ejecución. Agregue algunos botones y tendrá un "portal de administración". Si tiene un script Perl / Python / Ruby en ejecución, simplemente "lanzar un portal de administración" no es exactamente simple.

¿Pero no es JavaScript lento / malo / malvado / engendro del diablo? JavaScript tiene algunas rarezas extrañas, pero con "las partes buenas" hay un lenguaje muy poderoso allí, y en cualquier caso, JavaScript es EL lenguaje en el cliente (navegador). JavaScript está aquí para quedarse; otros idiomas lo están apuntando como un IL, y el talento de clase mundial está compitiendo para producir los motores JavaScript más avanzados. Debido al papel de JavaScript en el navegador, se está haciendo un enorme esfuerzo de ingeniería para hacer que JavaScript sea increíblemente rápido. V8es el último y mejor motor de JavaScript, al menos para este mes. Deslumbra a los otros lenguajes de secuencias de comandos tanto en eficiencia como en estabilidad (observándote, Ruby). Y solo va a mejorar con grandes equipos trabajando en el problema en Microsoft, Google y Mozilla, compitiendo para construir el mejor motor de JavaScript (ya no es un "intérprete" de JavaScript, ya que todos los motores modernos hacen toneladas de JITcompilando bajo el capó con interpretación solo como una alternativa para el código de ejecución única). Sí, todos deseamos poder solucionar algunas de las opciones de lenguaje JavaScript más extrañas, pero en realidad no es tan malo. Y el lenguaje es tan flexible que realmente no está codificando JavaScript, está codificando Step o jQuery, más que cualquier otro lenguaje, en JavaScript, las bibliotecas definen la experiencia. Para crear aplicaciones web, de todas formas debes saber JavaScript, por lo que codificarlo en el servidor tiene una especie de sinergia de habilidades. Me ha hecho no tener miedo de escribir el código del cliente.

Además, si REALMENTE odias JavaScript, puedes usar azúcar sintáctico como CoffeeScript . O cualquier otra cosa que cree código JavaScript, como Google Web Toolkit (GWT).

Hablando de JavaScript, ¿qué es un "cierre"? - Prácticamente una forma elegante de decir que retiene variables con ámbito léxico en las cadenas de llamadas. ;) Me gusta esto:

var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
    database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();

¿Ves cómo puedes usar "myData" sin hacer nada incómodo como guardarlo en un objeto? Y a diferencia de Java, la variable "myData" no tiene que ser de solo lectura. Esta poderosa característica del lenguaje hace que la programación asincrónica sea mucho menos detallada y menos dolorosa.

Escribir código asincrónico siempre será más complejo que escribir un script simple de un solo subproceso, pero con Node.js, no es mucho más difícil y obtienes muchos beneficios además de la eficiencia y la escalabilidad de miles de conexiones simultáneas. ..

Dave Dopson
fuente
"la variable 'myData' no tiene que ser de solo lectura", aunque parece que querrá mantenerla inmutable la mayor parte del tiempo para evitar problemas de concurrencia, ¿verdad?
Nick
1
@ Nick: eso es falso. Los "problemas de concurrencia" se mitigan por el hecho de que el nodo tiene un solo subproceso. El bloqueo en el nodo simplemente no existe; no es necesario en un paradigma de subproceso único.
Dave Dopson
El clúster se ha integrado en el núcleo del nodo en el nodo 0.6 stackoverflow.com/a/8470986/212702 nodejs.org/docs/latest/api/cluster.html#cluster_cluster
Laurent Debricon
1
ps, nota al margen: en realidad lo edité suficientes veces para que la publicación se convirtiera en "wiki de la comunidad" (el umbral es de 10 ediciones). Pensé erróneamente que esto era algún tipo de honor, cuando en realidad solo bloquea la ganancia de reputación de los votos positivos. Eventualmente, uno de los votantes anteriores al estado de CW hizo clic en "desestimar" (con suerte, por accidente :) y perdí reputación ... confundido, archivé meta.stackexchange.com/questions/129941/… y fui educado en qué "Comunidad Wiki "en realidad significa. Las modificaciones fueron lo suficientemente amables como para eliminar el estado de CW. :)
Dave Dopson
1
@John: mi comentario de depuración también se aplica absolutamente a vanilla asnyc. Para interrumpir la depuración, todo lo que necesito hacer es ajustar alguna llamada de función en "process.nextTick (...)". Luego, cuando se lanza, mi seguimiento de pila comenzará con process.nextTick; No tan útil. Lo que realmente quiero saber es: "¿qué pila de proceso programado.nextTick?" Llamo a esos datos "cadenas causales", y me recuerda a 'causeBy' en el manejo de excepciones de Java ... los lanzamientos de código de bajo nivel, el código de nivel medio captura la excepción LL y arroja FrameworkMethodFailedException - sin 'causeBy', la pila del LL El código se perdería.
Dave Dopson
85

V8 es una implementación de JavaScript. Le permite ejecutar aplicaciones JavaScript independientes (entre otras cosas).

Node.js es simplemente una biblioteca escrita para V8 que hace efecto I / O. Este concepto es un poco más complicado de explicar, y estoy seguro de que alguien responderá con una mejor explicación que yo ... La esencia es que, en lugar de hacer alguna entrada o salida y esperar que suceda, simplemente no esperes para que termine Entonces, por ejemplo, solicite la última hora editada de un archivo:

// Pseudo code
stat( 'somefile' )

Eso puede tomar un par de milisegundos, o puede tomar segundos. Con E / S igualadas , simplemente activa la solicitud y, en lugar de esperar, adjunta una devolución de llamada que se ejecuta cuando finaliza la solicitud:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

Esto se parece mucho al código JavaScript en el navegador (por ejemplo, con la funcionalidad de estilo Ajax ).

Para obtener más información, debe consultar el artículo Node.js es realmente emocionante, que fue mi introducción a la biblioteca / plataforma ... Lo encontré bastante bueno.

rfunduk
fuente
44
¿Cómo se implementa Evento IO sin usar bloqueos, subprocesos, procesos, cierres? Y tengo la sensación de que los conceptos son bastante similares a los de la programación funcional y Erlang.
Jeff
1
Se implementa como un simple bucle de eventos, que yo sepa. v8 ya tiene la funcionalidad de devolución de llamada / etc., al igual que cualquier implementación de JavaScript.
rfunduk
2
El bucle de eventos IO de node.js significa que, en cualquier momento dado, como máximo solo se está haciendo una cosa. Veo dos ganancias significativas: no hay una sobrecarga de conmutación de subprocesos, por lo que node.js es muy rápido y, en segundo lugar, muchos errores de concurrencia típicos por los que Java es notorio no son posibles.
nalply
1
"¿Cómo se implementa Evento IO sin usar ... cierres?" JavaScript admite cierres y se usan todo el tiempo en node.js (funciones anónimas y en el ejemplo aquí).
panzi
@panzi: No noté que Jeffrey incluyó cierres en su lista de cosas. node.js se implementa 'sin'. Obviamente, cada función en JavaScript es un cierre alrededor de su alcance :)
rfunduk
35

Node.js es una herramienta de línea de comandos de código abierto creada para el código JavaScript del lado del servidor. Puede descargar un tarball , compilar e instalar la fuente. Te permite ejecutar programas de JavaScript.

El JavaScript es ejecutado por el V8 , un motor de JavaScript desarrollado por Google que se utiliza en el navegador Chrome . Utiliza una API de JavaScript para acceder a la red y al sistema de archivos.

Es popular por su rendimiento y la capacidad de realizar operaciones paralelas.

Comprender node.js es la mejor explicación de node.js que he encontrado hasta ahora.

Los siguientes son algunos buenos artículos sobre el tema.

Asif Mushtaq
fuente
13

Los cierres son una forma de ejecutar código en el contexto en el que se creó.

Lo que esto significa para la concordancia es que puede definir variables, luego iniciar una función de E / S sin bloqueo y enviarle una función anónima para su devolución de llamada.

Cuando se completa la tarea, la función de devolución de llamada se ejecutará en el contexto con las variables, este es el cierre.

La razón por la cual los cierres son tan buenos para escribir aplicaciones con E / S sin bloqueo es que es muy fácil administrar el contexto de las funciones que se ejecutan de forma asincrónica.

Cuervo de fuego
fuente
8

Dos buenos ejemplos son sobre cómo administrar plantillas y usar mejoras progresivas con ellas. Solo necesita algunas piezas ligeras de código JavaScript para que funcione perfectamente.

Le recomiendo que mire y lea estos artículos:

Elija cualquier idioma e intente recordar cómo manejaría sus plantillas de archivo HTML y qué tenía que hacer para actualizar un solo nombre de clase CSS en su estructura DOM (por ejemplo, un usuario hizo clic en un elemento del menú y desea que se marque como "seleccionado" y actualizar el contenido de la página).

Con Node.js es tan simple como hacerlo en código JavaScript del lado del cliente. Obtenga su nodo DOM y aplique su clase CSS a eso. Obtenga su nodo DOM y innerHTML su contenido (necesitará un código JavaScript adicional para hacerlo. Lea el artículo para obtener más información).

Otro buen ejemplo es que puede hacer que su página web sea compatible tanto con JavaScript activado como desactivado con el mismo código. Imagine que tiene una selección de fecha hecha en JavaScript que permitiría a sus usuarios elegir cualquier fecha usando un calendario. Puede escribir (o usar) el mismo código de JavaScript para que funcione con su JavaScript activado o desactivado.

Renato
fuente
7

Existe una muy buena analogía de lugares de comida rápida que explica mejor el modelo de Node.js basado en eventos, vea el artículo completo, Node.js, Consultorios médicos y restaurantes de comida rápida: comprensión de la programación basada en eventos

Aquí hay un resumen:

Si el restaurante de comida rápida siguiera un modelo tradicional basado en hilos, pediría su comida y esperaría en línea hasta que la recibiera. La persona detrás de usted no podrá realizar el pedido hasta que se haya realizado su pedido. En un modelo basado en eventos, usted ordena su comida y luego se sale de la fila para esperar. Todos los demás son libres de ordenar.

Node.js está basado en eventos, pero la mayoría de los servidores web están basados ​​en hilos. York explica cómo funciona Node.js:

  • Utiliza su navegador web para realizar una solicitud de "/about.html" en un servidor web Node.js.

  • El servidor Node.js acepta su solicitud y llama a una función para recuperar ese archivo del disco.

  • Mientras el servidor Node.js está esperando que se recupere el archivo, atiende la siguiente solicitud web.

  • Cuando se recupera el archivo, hay una función de devolución de llamada que se inserta en la cola de servidores Node.js.

  • El servidor Node.js ejecuta esa función que en este caso representaría la página "/about.html" y la devolvería a su navegador web ".

adeleinr
fuente
6

Bueno, entiendo que

  • El objetivo de Node es proporcionar una manera fácil de construir programas de red escalables.
  • El nodo es similar en diseño e influenciado por sistemas como Ruby's Event Machine o Python's Twisted.
  • Evented I / O para V8 javascript.

Para mí eso significa que estabas en lo correcto en los tres supuestos. ¡La biblioteca parece prometedora!

nes1983
fuente
1
Muchas de las veces que encuentro sobre page es bastante vago.
Jeff
6

Además, no olvide mencionar que el V8 de Google es MUY rápido. En realidad, convierte el código JavaScript en código máquina con el rendimiento coincidente del binario compilado. Entonces, junto con todas las otras grandes cosas, es increíblemente rápido.

Quinton Pike
fuente
3

Q: El modelo de programación está dirigida por eventos, especialmente por la forma en que maneja E / S .

Correcto. Utiliza devoluciones de llamada, por lo que cualquier solicitud de acceso al sistema de archivos provocaría que se enviara una solicitud al sistema de archivos y luego Node.js comenzaría a procesar su próxima solicitud. Solo se preocuparía por la solicitud de E / S una vez que reciba una respuesta del sistema de archivos, momento en el que ejecutará el código de devolución de llamada. Sin embargo, es posible realizar solicitudes de E / S sincrónicas (es decir, solicitudes de bloqueo). Depende del desarrollador elegir entre asíncrono (devoluciones de llamada) o sincrónico (en espera).

P: Utiliza JavaScript y el analizador es V8.

si

P: Se puede usar fácilmente para crear aplicaciones de servidor concurrentes.

Sí, aunque necesitaría codificar a mano una gran cantidad de JavaScript. Sería mejor mirar un marco, como http://www.easynodejs.com/ , que viene con documentación completa en línea y una aplicación de muestra.

Charles
fuente